diff --git a/.drone.yml b/.drone.yml index 8b9f15919..5c68e2ccb 100644 --- a/.drone.yml +++ b/.drone.yml @@ -21,7 +21,13 @@ steps: - name: cargo clippy image: ekidd/rust-musl-builder:1.50.0 + environment: + CARGO_HOME: /drone/src/.cargo 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 -- -D clippy::unwrap_used @@ -30,6 +36,8 @@ steps: environment: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy RUST_BACKTRACE: 1 + RUST_TEST_THREADS: 1 + CARGO_HOME: /drone/src/.cargo commands: - sudo apt-get update - sudo apt-get -y install --no-install-recommends espeak postgresql-client @@ -37,6 +45,8 @@ steps: - name: cargo build image: ekidd/rust-musl-builder:1.50.0 + environment: + CARGO_HOME: /drone/src/.cargo commands: - cargo build - mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server @@ -107,6 +117,8 @@ steps: environment: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy RUST_BACKTRACE: 1 + RUST_TEST_THREADS: 1 + CARGO_HOME: /drone/src/.cargo commands: - apt-get update - apt-get -y install --no-install-recommends espeak postgresql-client libssl-dev pkg-config libpq-dev @@ -116,6 +128,8 @@ steps: # Using Debian here because there seems to be no official Alpine-based Rust docker image for ARM. - name: cargo build image: rust:1.50-slim-buster + environment: + CARGO_HOME: /drone/src/.cargo commands: - apt-get update - apt-get -y install --no-install-recommends libssl-dev pkg-config libpq-dev diff --git a/Cargo.lock b/Cargo.lock index a4b9fcc82..b525d65a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -144,8 +144,8 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" dependencies = [ - "quote", - "syn", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -333,9 +333,9 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -344,9 +344,9 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -406,9 +406,9 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -916,10 +916,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b" dependencies = [ "fnv", "ident_case", - "proc-macro2", - "quote", + "proc-macro2 1.0.24", + "quote 1.0.8", "strsim", - "syn", + "syn 1.0.60", ] [[package]] @@ -929,8 +929,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72" dependencies = [ "darling_core", - "quote", - "syn", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -951,9 +951,9 @@ checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0" dependencies = [ "darling", "derive_builder_core", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -963,9 +963,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef" dependencies = [ "darling", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -974,9 +974,9 @@ version = "0.99.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -1003,15 +1003,27 @@ dependencies = [ "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]] name = "diesel_derives" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -1085,9 +1097,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -1253,9 +1265,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd" dependencies = [ "proc-macro-hack", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -1852,6 +1864,7 @@ version = "0.1.0" dependencies = [ "chrono", "diesel", + "diesel-derive-newtype", "log", "serde", "serde_json", @@ -2144,9 +2157,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07" dependencies = [ "proc-macro-error", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -2165,9 +2178,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c" dependencies = [ "migrations_internals", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -2475,9 +2488,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -2515,9 +2528,9 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -2526,9 +2539,9 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -2589,9 +2602,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", "version_check", ] @@ -2601,8 +2614,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.24", + "quote 1.0.8", "version_check", ] @@ -2618,13 +2631,22 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" 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]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.1", ] [[package]] @@ -2643,13 +2665,22 @@ dependencies = [ "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]] name = "quote" version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.24", ] [[package]] @@ -3032,9 +3063,9 @@ version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -3078,9 +3109,9 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -3211,11 +3242,11 @@ version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.24", + "quote 1.0.8", "serde", "serde_derive", - "syn", + "syn 1.0.60", ] [[package]] @@ -3225,13 +3256,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" dependencies = [ "base-x", - "proc-macro2", - "quote", + "proc-macro2 1.0.24", + "quote 1.0.8", "serde", "serde_derive", "serde_json", "sha1", - "syn", + "syn 1.0.60", ] [[package]] @@ -3259,9 +3290,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149" dependencies = [ "heck", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "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]] @@ -3270,9 +3312,9 @@ version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.24", + "quote 1.0.8", + "unicode-xid 0.2.1", ] [[package]] @@ -3319,9 +3361,9 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", ] [[package]] @@ -3396,10 +3438,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa" dependencies = [ "proc-macro-hack", - "proc-macro2", - "quote", + "proc-macro2 1.0.24", + "quote 1.0.8", "standback", - "syn", + "syn 1.0.60", ] [[package]] @@ -3635,6 +3677,12 @@ version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.1" @@ -3731,9 +3779,9 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", "wasm-bindgen-shared", ] @@ -3755,7 +3803,7 @@ version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" dependencies = [ - "quote", + "quote 1.0.8", "wasm-bindgen-macro-support", ] @@ -3765,9 +3813,9 @@ version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" dependencies = [ - "proc-macro2", - "quote", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.8", + "syn 1.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] diff --git a/ansible/VERSION b/ansible/VERSION index 7e310bae1..4bcce4252 100644 --- a/ansible/VERSION +++ b/ansible/VERSION @@ -1 +1 @@ -0.9.9 +0.10.0-rc.5 diff --git a/ansible/templates/docker-compose.yml b/ansible/templates/docker-compose.yml index 7e81e8039..b074d60fe 100644 --- a/ansible/templates/docker-compose.yml +++ b/ansible/templates/docker-compose.yml @@ -38,13 +38,14 @@ services: restart: always pictrs: - image: asonix/pictrs:v0.2.5-r0 + image: asonix/pictrs:v0.2.6-r1 user: 991:991 ports: - "127.0.0.1:8537:8080" volumes: - ./volumes/pictrs:/mnt restart: always + mem_limit: 200m iframely: image: dogbin/iframely:latest diff --git a/api_tests/package.json b/api_tests/package.json index e2c4f37a0..d4232ed53 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -16,7 +16,7 @@ "eslint": "^7.18.0", "eslint-plugin-jane": "^9.0.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", "prettier": "^2.1.2", "ts-jest": "^26.4.4", diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index 25d8109c3..7be6f4c59 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -33,9 +33,6 @@ function assertCommunityFederation( ); expect(communityOne.creator.actor_id).toBe(communityTwo.creator.actor_id); 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.deleted).toBe(communityTwo.community.deleted); } diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index 0d1788c62..db5f3edee 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -20,10 +20,10 @@ import { getPost, unfollowRemotes, searchForUser, - banUserFromSite, + banPersonFromSite, searchPostLocal, - banUserFromCommunity, followCommunity, + banPersonFromCommunity, } from './shared'; import { PostView, CommunityView } from 'lemmy-js-client'; @@ -309,7 +309,7 @@ test('Enforce site ban for federated user', async () => { expect(alphaUser).toBeDefined(); // 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); // Alpha makes post on beta @@ -325,7 +325,7 @@ test('Enforce site ban for federated user', async () => { expect(betaPost).toBeUndefined(); // 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); }); @@ -336,8 +336,8 @@ test('Enforce community ban for federated user', async () => { expect(alphaUser).toBeDefined(); // ban alpha from beta site - await banUserFromCommunity(beta, alphaUser.user.id, 2, false); - let banAlpha = await banUserFromCommunity(beta, alphaUser.user.id, 2, true); + await banPersonFromCommunity(beta, alphaUser.person.id, 2, false); + let banAlpha = await banPersonFromCommunity(beta, alphaUser.person.id, 2, true); expect(banAlpha.banned).toBe(true); // Alpha makes post on beta @@ -353,9 +353,9 @@ test('Enforce community ban for federated user', async () => { expect(betaPost).toBeUndefined(); // Unban alpha - let unBanAlpha = await banUserFromCommunity( + let unBanAlpha = await banPersonFromCommunity( beta, - alphaUser.user.id, + alphaUser.person.id, 2, false ); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 0c12d29c0..c11fa3b0e 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -25,7 +25,7 @@ import { CreateCommunity, DeleteCommunity, RemoveCommunity, - GetUserMentions, + GetPersonMentions, CreateCommentLike, CreatePostLike, EditPrivateMessage, @@ -36,15 +36,15 @@ import { GetPost, PrivateMessageResponse, PrivateMessagesResponse, - GetUserMentionsResponse, + GetPersonMentionsResponse, SaveUserSettings, SortType, ListingType, GetSiteResponse, SearchType, LemmyHttp, - BanUserResponse, - BanUser, + BanPersonResponse, + BanPerson, BanFromCommunity, BanFromCommunityResponse, Post, @@ -289,32 +289,32 @@ export async function searchForUser( return api.client.search(form); } -export async function banUserFromSite( +export async function banPersonFromSite( api: API, - user_id: number, + person_id: number, ban: boolean -): Promise { +): Promise { // Make sure lemmy-beta/c/main is cached on lemmy_alpha // Use short-hand search url - let form: BanUser = { - user_id, + let form: BanPerson = { + person_id, ban, remove_data: false, auth: api.auth, }; - return api.client.banUser(form); + return api.client.banPerson(form); } -export async function banUserFromCommunity( +export async function banPersonFromCommunity( api: API, - user_id: number, + person_id: number, community_id: number, ban: boolean ): Promise { // Make sure lemmy-beta/c/main is cached on lemmy_alpha // Use short-hand search url let form: BanFromCommunity = { - user_id, + person_id, community_id, remove_data: false, ban, @@ -413,13 +413,13 @@ export async function removeComment( return api.client.removeComment(form); } -export async function getMentions(api: API): Promise { - let form: GetUserMentions = { +export async function getMentions(api: API): Promise { + let form: GetPersonMentions = { sort: SortType.New, unread_only: false, auth: api.auth, }; - return api.client.getUserMentions(form); + return api.client.getPersonMentions(form); } export async function likeComment( @@ -448,7 +448,6 @@ export async function createCommunity( description, icon, banner, - category_id: 1, nsfw: false, auth: api.auth, }; diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index 4352aa423..a10876cf5 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -8,7 +8,7 @@ import { getSite, } from './shared'; import { - UserViewSafe, + PersonViewSafe, SaveUserSettings, SortType, ListingType, @@ -17,14 +17,14 @@ import { let auth: string; let apShortname: string; -function assertUserFederation(userOne: UserViewSafe, userTwo: UserViewSafe) { - expect(userOne.user.name).toBe(userTwo.user.name); - expect(userOne.user.preferred_username).toBe(userTwo.user.preferred_username); - expect(userOne.user.bio).toBe(userTwo.user.bio); - expect(userOne.user.actor_id).toBe(userTwo.user.actor_id); - expect(userOne.user.avatar).toBe(userTwo.user.avatar); - expect(userOne.user.banner).toBe(userTwo.user.banner); - expect(userOne.user.published).toBe(userTwo.user.published); +function assertUserFederation(userOne: PersonViewSafe, userTwo: PersonViewSafe) { + expect(userOne.person.name).toBe(userTwo.person.name); + expect(userOne.person.preferred_username).toBe(userTwo.person.preferred_username); + expect(userOne.person.bio).toBe(userTwo.person.bio); + expect(userOne.person.actor_id).toBe(userTwo.person.actor_id); + expect(userOne.person.avatar).toBe(userTwo.person.avatar); + expect(userOne.person.banner).toBe(userTwo.person.banner); + expect(userOne.person.published).toBe(userTwo.person.published); } test('Create user', async () => { @@ -34,7 +34,7 @@ test('Create user', async () => { let site = await getSite(alpha, auth); 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 () => { diff --git a/api_tests/yarn.lock b/api_tests/yarn.lock index 8e29aa041..a6d1be5a3 100644 --- a/api_tests/yarn.lock +++ b/api_tests/yarn.lock @@ -3233,10 +3233,10 @@ language-tags@^1.0.5: dependencies: language-subtag-registry "~0.3.2" -lemmy-js-client@0.9.1-rc.1: - version "0.9.1-rc.1" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.9.1-rc.1.tgz#afe3cb0d4852f849dd087a4756a3771bc920a907" - integrity sha512-aVvo4IeJvIPUvypipk4GnyLB6nVQVLfB0arYrMkVV4L7zrZ/0pGtpkMDLaOAj/KpA6O0u9eLmaou5RberZQolA== +lemmy-js-client@0.10.0-rc.4: + version "0.10.0-rc.4" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.10.0-rc.4.tgz#ac6fe6940fc5f73260ddb166ce0ef3c0520901fc" + integrity sha512-yJPnvGaWneOOwjKEqb4qXtQk+4DbRgO+hEzSin2GgUgnxluY43gemwiCPt6EnV+j4ueKoi0+QORVg2RuRC2PaQ== leven@^3.1.0: version "3.1.0" diff --git a/crates/api/src/comment.rs b/crates/api/src/comment.rs index cb8b2d515..4fd3f7b2c 100644 --- a/crates/api/src/comment.rs +++ b/crates/api/src/comment.rs @@ -2,9 +2,9 @@ use crate::{ check_community_ban, check_downvotes_enabled, collect_moderated_communities, + get_local_user_view_from_jwt, + get_local_user_view_from_jwt_opt, get_post, - get_user_from_jwt, - get_user_from_jwt_opt, is_mod_or_admin, Perform, }; @@ -20,10 +20,14 @@ use lemmy_db_queries::{ Saveable, SortType, }; -use lemmy_db_schema::source::{comment::*, comment_report::*, moderator::*}; +use lemmy_db_schema::{ + source::{comment::*, comment_report::*, moderator::*}, + LocalUserId, +}; use lemmy_db_views::{ comment_report_view::{CommentReportQueryBuilder, CommentReportView}, comment_view::{CommentQueryBuilder, CommentView}, + local_user_view::LocalUserView, }; use lemmy_utils::{ utils::{remove_slurs, scrape_text_for_mentions}, @@ -48,7 +52,7 @@ impl Perform for CreateComment { websocket_id: Option, ) -> Result { 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()); @@ -56,7 +60,7 @@ impl Perform for CreateComment { let post_id = data.post_id; 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 if post.locked { @@ -80,7 +84,7 @@ impl Perform for CreateComment { content: content_slurs_removed, parent_id: data.parent_id.to_owned(), post_id: data.post_id, - creator_id: user.id, + creator_id: local_user_view.person.id, removed: None, deleted: None, read: None, @@ -115,7 +119,9 @@ impl Perform for CreateComment { 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 let post_id = post.id; @@ -123,7 +129,7 @@ impl Perform for CreateComment { let recipient_ids = send_local_notifs( mentions, updated_comment.clone(), - &user, + local_user_view.person.clone(), post, context.pool(), true, @@ -134,7 +140,7 @@ impl Perform for CreateComment { let like_form = CommentLikeForm { comment_id: inserted_comment.id, post_id, - user_id: user.id, + person_id: local_user_view.person.id, score: 1, }; @@ -143,17 +149,19 @@ impl Perform for CreateComment { 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| { - CommentView::read(&conn, inserted_comment.id, Some(user_id)) + CommentView::read(&conn, inserted_comment.id, Some(person_id)) }) .await??; // If its a comment to yourself, mark it as read 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| { Comment::update_read(conn, comment_id, true) }) @@ -193,7 +201,7 @@ impl Perform for EditComment { websocket_id: Option, ) -> Result { 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 orig_comment = blocking(context.pool(), move |conn| { @@ -201,10 +209,15 @@ impl Perform for EditComment { }) .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 - 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()); } @@ -221,7 +234,9 @@ impl Perform for EditComment { }; // 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 let updated_comment_content = updated_comment.content.to_owned(); @@ -229,7 +244,7 @@ impl Perform for EditComment { let recipient_ids = send_local_notifs( mentions, updated_comment, - &user, + local_user_view.person.clone(), orig_comment.post, context.pool(), false, @@ -237,9 +252,9 @@ impl Perform for EditComment { .await?; 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -269,7 +284,7 @@ impl Perform for DeleteComment { websocket_id: Option, ) -> Result { 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 orig_comment = blocking(context.pool(), move |conn| { @@ -277,10 +292,15 @@ impl Perform for DeleteComment { }) .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 - 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()); } @@ -297,16 +317,20 @@ impl Perform for DeleteComment { // Send the apub message if deleted { - updated_comment.send_delete(&user, context).await?; + updated_comment + .send_delete(&local_user_view.person, context) + .await?; } else { - updated_comment.send_undo_delete(&user, context).await?; + updated_comment + .send_undo_delete(&local_user_view.person, context) + .await?; } // Refetch it 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -316,7 +340,7 @@ impl Perform for DeleteComment { let recipient_ids = send_local_notifs( mentions, updated_comment, - &user, + local_user_view.person.clone(), comment_view_2.post, context.pool(), false, @@ -349,7 +373,7 @@ impl Perform for RemoveComment { websocket_id: Option, ) -> Result { 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 orig_comment = blocking(context.pool(), move |conn| { @@ -357,10 +381,20 @@ impl Perform for RemoveComment { }) .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 - 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 let removed = data.removed; @@ -375,7 +409,7 @@ impl Perform for RemoveComment { // Mod tables let form = ModRemoveCommentForm { - mod_user_id: user.id, + mod_person_id: local_user_view.person.id, comment_id: data.comment_id, removed: Some(removed), reason: data.reason.to_owned(), @@ -387,16 +421,20 @@ impl Perform for RemoveComment { // Send the apub message if removed { - updated_comment.send_remove(&user, context).await?; + updated_comment + .send_remove(&local_user_view.person, context) + .await?; } else { - updated_comment.send_undo_remove(&user, context).await?; + updated_comment + .send_undo_remove(&local_user_view.person, context) + .await?; } // Refetch it 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -407,7 +445,7 @@ impl Perform for RemoveComment { let recipient_ids = send_local_notifs( mentions, updated_comment, - &user, + local_user_view.person.clone(), comment_view_2.post, context.pool(), false, @@ -440,7 +478,7 @@ impl Perform for MarkCommentAsRead { _websocket_id: Option, ) -> Result { 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 orig_comment = blocking(context.pool(), move |conn| { @@ -448,10 +486,15 @@ impl Perform for MarkCommentAsRead { }) .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 - 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()); } @@ -468,9 +511,9 @@ impl Perform for MarkCommentAsRead { // Refetch it 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -494,11 +537,11 @@ impl Perform for SaveComment { _websocket_id: Option, ) -> Result { 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 { comment_id: data.comment_id, - user_id: user.id, + person_id: local_user_view.person.id, }; if data.save { @@ -514,9 +557,9 @@ impl Perform for SaveComment { } 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -538,9 +581,9 @@ impl Perform for CreateCommentLike { websocket_id: Option, ) -> Result { 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::::new(); // Don't do a downvote if site has downvotes disabled check_downvotes_enabled(data.score, context.pool()).await?; @@ -551,22 +594,34 @@ impl Perform for CreateCommentLike { }) .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 - 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 { comment_id: data.comment_id, post_id: orig_comment.post.id, - user_id: user.id, + person_id: local_user_view.person.id, score: data.score, }; // Remove any likes first - let user_id = user.id; + let person_id = local_user_view.person.id; blocking(context.pool(), move |conn| { - CommentLike::remove(conn, user_id, comment_id) + CommentLike::remove(conn, person_id, comment_id) }) .await??; @@ -581,19 +636,23 @@ impl Perform for CreateCommentLike { } 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 { - comment.send_dislike(&user, context).await?; + comment + .send_dislike(&local_user_view.person, context) + .await?; } } 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 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| { - CommentView::read(conn, comment_id, Some(user_id)) + CommentView::read(conn, comment_id, Some(person_id)) }) .await??; @@ -623,8 +682,8 @@ impl Perform for GetComments { _websocket_id: Option, ) -> Result { let data: &GetComments = &self; - let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; - let user_id = user.map(|u| u.id); + let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; + let person_id = local_user_view.map(|u| u.person.id); let type_ = ListingType::from_str(&data.type_)?; let sort = SortType::from_str(&data.sort)?; @@ -639,7 +698,7 @@ impl Perform for GetComments { .sort(&sort) .community_id(community_id) .community_name(community_name) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -665,7 +724,7 @@ impl Perform for CreateCommentReport { websocket_id: Option, ) -> Result { 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 let reason = data.reason.trim(); @@ -676,17 +735,17 @@ impl Perform for CreateCommentReport { 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_view = blocking(context.pool(), move |conn| { CommentView::read(&conn, comment_id, None) }) .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 { - creator_id: user_id, + creator_id: person_id, comment_id, original_comment_text: comment_view.comment.content, reason: data.reason.to_owned(), @@ -706,7 +765,7 @@ impl Perform for CreateCommentReport { context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::CreateCommentReport, response: res.clone(), - recipient_id: user.id, + local_recipient_id: local_user_view.local_user.id, websocket_id, }); @@ -732,7 +791,7 @@ impl Perform for ResolveCommentReport { websocket_id: Option, ) -> Result { 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 = blocking(context.pool(), move |conn| { @@ -740,15 +799,15 @@ impl Perform for ResolveCommentReport { }) .await??; - let user_id = user.id; - is_mod_or_admin(context.pool(), user_id, report.community.id).await?; + let person_id = local_user_view.person.id; + is_mod_or_admin(context.pool(), person_id, report.community.id).await?; let resolved = data.resolved; let resolve_fun = move |conn: &'_ _| { if resolved { - CommentReport::resolve(conn, report_id, user_id) + CommentReport::resolve(conn, report_id, person_id) } 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, ) -> Result { 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_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 limit = data.limit; @@ -808,7 +867,7 @@ impl Perform for ListCommentReports { context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::ListCommentReports, response: res.clone(), - recipient_id: user.id, + local_recipient_id: local_user_view.local_user.id, websocket_id, }); diff --git a/crates/api/src/community.rs b/crates/api/src/community.rs index 0bb64f373..f7e8e23ce 100644 --- a/crates/api/src/community.rs +++ b/crates/api/src/community.rs @@ -1,7 +1,7 @@ use crate::{ check_community_ban, - get_user_from_jwt, - get_user_from_jwt_opt, + get_local_user_view_from_jwt, + get_local_user_view_from_jwt_opt, is_admin, is_mod_or_admin, Perform, @@ -36,14 +36,15 @@ use lemmy_db_queries::{ }; use lemmy_db_schema::{ naive_now, - source::{comment::Comment, community::*, moderator::*, post::Post, site::*, user::User_}, + source::{comment::Comment, community::*, moderator::*, person::Person, post::Post, site::*}, + PersonId, }; use lemmy_db_views::comment_view::CommentQueryBuilder; use lemmy_db_views_actor::{ community_follower_view::CommunityFollowerView, community_moderator_view::CommunityModeratorView, community_view::{CommunityQueryBuilder, CommunityView}, - user_view::UserViewSafe, + person_view::PersonViewSafe, }; use lemmy_utils::{ apub::generate_actor_keypair, @@ -70,8 +71,8 @@ impl Perform for GetCommunity { _websocket_id: Option, ) -> Result { let data: &GetCommunity = &self; - let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; - let user_id = user.map(|u| u.id); + let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; + let person_id = local_user_view.map(|u| u.person.id); let community_id = match data.id { Some(id) => id, @@ -90,7 +91,7 @@ impl Perform for GetCommunity { }; let community_view = match blocking(context.pool(), move |conn| { - CommunityView::read(conn, community_id, user_id) + CommunityView::read(conn, community_id, person_id) }) .await? { @@ -134,7 +135,7 @@ impl Perform for CreateCommunity { _websocket_id: Option, ) -> Result { 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.title)?; @@ -168,7 +169,7 @@ impl Perform for CreateCommunity { description: data.description.to_owned(), icon, banner, - creator_id: user.id, + creator_id: local_user_view.person.id, removed: None, deleted: None, nsfw: data.nsfw, @@ -196,7 +197,7 @@ impl Perform for CreateCommunity { // The community creator becomes a moderator let community_moderator_form = CommunityModeratorForm { 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); @@ -207,7 +208,7 @@ impl Perform for CreateCommunity { // Follow your own community let community_follower_form = CommunityFollowerForm { community_id: inserted_community.id, - user_id: user.id, + person_id: local_user_view.person.id, pending: false, }; @@ -216,9 +217,9 @@ impl Perform for CreateCommunity { 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| { - CommunityView::read(conn, inserted_community.id, Some(user_id)) + CommunityView::read(conn, inserted_community.id, Some(person_id)) }) .await??; @@ -236,19 +237,19 @@ impl Perform for EditCommunity { websocket_id: Option, ) -> Result { 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_opt(&data.description)?; // Verify its a mod (only mods can edit it) let community_id = data.community_id; - let mods: Vec = blocking(context.pool(), move |conn| { + let mods: Vec = blocking(context.pool(), move |conn| { CommunityModeratorView::for_community(conn, community_id) .map(|v| v.into_iter().map(|m| m.moderator.id).collect()) }) .await??; - if !mods.contains(&user.id) { + if !mods.contains(&local_user_view.person.id) { return Err(ApiError::err("not_a_moderator").into()); } @@ -297,9 +298,9 @@ impl Perform for EditCommunity { // process for communities and users 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| { - CommunityView::read(conn, community_id, Some(user_id)) + CommunityView::read(conn, community_id, Some(person_id)) }) .await??; @@ -321,7 +322,7 @@ impl Perform for DeleteCommunity { websocket_id: Option, ) -> Result { 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) let community_id = data.community_id; @@ -329,7 +330,7 @@ impl Perform for DeleteCommunity { Community::read(conn, community_id) }) .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()); } @@ -353,9 +354,9 @@ impl Perform for DeleteCommunity { } 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| { - CommunityView::read(conn, community_id, Some(user_id)) + CommunityView::read(conn, community_id, Some(person_id)) }) .await??; @@ -377,10 +378,10 @@ impl Perform for RemoveCommunity { websocket_id: Option, ) -> Result { 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) - is_admin(context.pool(), user.id).await?; + is_admin(&local_user_view)?; // Do the remove let community_id = data.community_id; @@ -400,7 +401,7 @@ impl Perform for RemoveCommunity { None => None, }; let form = ModRemoveCommunityForm { - mod_user_id: user.id, + mod_person_id: local_user_view.person.id, community_id: data.community_id, removed: Some(removed), reason: data.reason.to_owned(), @@ -419,9 +420,9 @@ impl Perform for RemoveCommunity { } 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| { - CommunityView::read(conn, community_id, Some(user_id)) + CommunityView::read(conn, community_id, Some(person_id)) }) .await??; @@ -443,15 +444,16 @@ impl Perform for ListCommunities { _websocket_id: Option, ) -> Result { 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 { - Some(user) => Some(user.id), + let person_id = match &local_user_view { + Some(uv) => Some(uv.person.id), None => None, }; - let show_nsfw = match &user { - Some(user) => user.show_nsfw, + // Don't show NSFW by default + let show_nsfw = match &local_user_view { + Some(uv) => uv.local_user.show_nsfw, None => false, }; @@ -465,7 +467,7 @@ impl Perform for ListCommunities { .listing_type(&type_) .sort(&sort) .show_nsfw(show_nsfw) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -487,7 +489,7 @@ impl Perform for FollowCommunity { _websocket_id: Option, ) -> Result { 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 = blocking(context.pool(), move |conn| { @@ -496,13 +498,13 @@ impl Perform for FollowCommunity { .await??; let community_follower_form = CommunityFollowerForm { community_id: data.community_id, - user_id: user.id, + person_id: local_user_view.person.id, pending: false, }; if community.local { 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); if blocking(context.pool(), follow).await?.is_err() { @@ -518,9 +520,15 @@ impl Perform for FollowCommunity { } else if data.follow { // Dont actually add to the community followers here, because you need // 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 { - 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); if blocking(context.pool(), unfollow).await?.is_err() { return Err(ApiError::err("community_follower_already_exists").into()); @@ -528,9 +536,9 @@ impl Perform for FollowCommunity { } 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| { - CommunityView::read(conn, community_id, Some(user_id)) + CommunityView::read(conn, community_id, Some(person_id)) }) .await??; @@ -555,11 +563,11 @@ impl Perform for GetFollowedCommunities { _websocket_id: Option, ) -> Result { 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| { - CommunityFollowerView::for_user(conn, user_id) + CommunityFollowerView::for_person(conn, person_id) }) .await? { @@ -582,21 +590,21 @@ impl Perform for BanFromCommunity { websocket_id: Option, ) -> Result { 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 banned_user_id = data.user_id; + let banned_person_id = data.person_id; // 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, - user_id: data.user_id, + person_id: data.person_id, }; 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() { return Err(ApiError::err("community_user_already_banned").into()); } @@ -604,7 +612,7 @@ impl Perform for BanFromCommunity { // Also unsubscribe them from the community, if they are subscribed let community_follower_form = CommunityFollowerForm { community_id: data.community_id, - user_id: banned_user_id, + person_id: banned_person_id, pending: false, }; blocking(context.pool(), move |conn: &'_ _| { @@ -613,7 +621,7 @@ impl Perform for BanFromCommunity { .await? .ok(); } 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() { return Err(ApiError::err("community_user_already_banned").into()); } @@ -623,7 +631,7 @@ impl Perform for BanFromCommunity { if data.remove_data { // Posts 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??; @@ -631,7 +639,7 @@ impl Perform for BanFromCommunity { // TODO Diesel doesn't allow updates with joins, so this has to be a loop let comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) - .creator_id(banned_user_id) + .creator_id(banned_person_id) .community_id(community_id) .limit(std::i64::MAX) .list() @@ -655,8 +663,8 @@ impl Perform for BanFromCommunity { }; let form = ModBanFromCommunityForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: data.person_id, community_id: data.community_id, reason: data.reason.to_owned(), banned: Some(data.ban), @@ -667,14 +675,14 @@ impl Perform for BanFromCommunity { }) .await??; - let user_id = data.user_id; - let user_view = blocking(context.pool(), move |conn| { - UserViewSafe::read(conn, user_id) + let person_id = data.person_id; + let person_view = blocking(context.pool(), move |conn| { + PersonViewSafe::read(conn, person_id) }) .await??; let res = BanFromCommunityResponse { - user_view, + person_view, banned: data.ban, }; @@ -699,17 +707,17 @@ impl Perform for AddModToCommunity { websocket_id: Option, ) -> Result { 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_id = data.community_id; // 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?; // Update in local database let community_moderator_form = CommunityModeratorForm { community_id: data.community_id, - user_id: data.user_id, + person_id: data.person_id, }; if data.added { let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); @@ -725,8 +733,8 @@ impl Perform for AddModToCommunity { // Mod tables let form = ModAddCommunityForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: data.person_id, community_id: data.community_id, removed: Some(!data.added), }; @@ -736,9 +744,9 @@ impl Perform for AddModToCommunity { .await??; // Send to federated instances - let updated_mod_id = data.user_id; + let updated_mod_id = data.person_id; let updated_mod = blocking(context.pool(), move |conn| { - User_::read(conn, updated_mod_id) + Person::read(conn, updated_mod_id) }) .await??; let community = blocking(context.pool(), move |conn| { @@ -746,10 +754,12 @@ impl Perform for AddModToCommunity { }) .await??; if data.added { - community.send_add_mod(&user, updated_mod, context).await?; + community + .send_add_mod(&local_user_view.person, updated_mod, context) + .await?; } else { community - .send_remove_mod(&user, updated_mod, context) + .send_remove_mod(&local_user_view.person, updated_mod, context) .await?; } @@ -784,7 +794,7 @@ impl Perform for TransferCommunity { _websocket_id: Option, ) -> Result { 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 read_community = blocking(context.pool(), move |conn| { @@ -797,25 +807,28 @@ impl Perform for TransferCommunity { }) .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 let creator_index = admins .iter() - .position(|r| r.user.id == site_creator_id) + .position(|r| r.person.id == site_creator_id) .context(location_info!())?; - let creator_user = admins.remove(creator_index); - admins.insert(0, creator_user); + let creator_person = admins.remove(creator_index); + admins.insert(0, creator_person); // Make sure user is the creator, or an admin - if user.id != read_community.creator_id - && !admins.iter().map(|a| a.user.id).any(|x| x == user.id) + if local_user_view.person.id != read_community.creator_id + && !admins + .iter() + .map(|a| a.person.id) + .any(|x| x == local_user_view.person.id) { return Err(ApiError::err("not_an_admin").into()); } 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); if blocking(context.pool(), update).await?.is_err() { return Err(ApiError::err("couldnt_update_community").into()); @@ -829,10 +842,10 @@ impl Perform for TransferCommunity { .await??; let creator_index = community_mods .iter() - .position(|r| r.moderator.id == data.user_id) + .position(|r| r.moderator.id == data.person_id) .context(location_info!())?; - let creator_user = community_mods.remove(creator_index); - community_mods.insert(0, creator_user); + let creator_person = community_mods.remove(creator_index); + community_mods.insert(0, creator_person); let community_id = data.community_id; blocking(context.pool(), move |conn| { @@ -844,7 +857,7 @@ impl Perform for TransferCommunity { for cmod in &community_mods { let community_moderator_form = CommunityModeratorForm { 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); @@ -855,8 +868,8 @@ impl Perform for TransferCommunity { // Mod tables let form = ModAddCommunityForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: data.person_id, community_id: data.community_id, removed: Some(false), }; @@ -866,9 +879,9 @@ impl Perform for TransferCommunity { .await??; 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| { - CommunityView::read(conn, community_id, Some(user_id)) + CommunityView::read(conn, community_id, Some(person_id)) }) .await? { @@ -901,7 +914,7 @@ fn send_community_websocket( websocket_id: Option, 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(); res_sent.community_view.subscribed = false; diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index d87375ca7..a2e9bfede 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -3,28 +3,33 @@ use lemmy_api_structs::{ blocking, comment::*, community::*, + person::*, post::*, site::*, - user::*, websocket::*, }; use lemmy_db_queries::{ source::{ community::{CommunityModerator_, Community_}, site::Site_, - user::UserSafeSettings_, }, Crud, DbPool, }; -use lemmy_db_schema::source::{ - community::{Community, CommunityModerator}, - post::Post, - site::Site, - user::{UserSafeSettings, User_}, +use lemmy_db_schema::{ + source::{ + community::{Community, CommunityModerator}, + post::Post, + site::Site, + }, + CommunityId, + LocalUserId, + PersonId, + PostId, }; +use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView}; use lemmy_db_views_actor::{ - community_user_ban_view::CommunityUserBanView, + community_person_ban_view::CommunityPersonBanView, community_view::CommunityView, }; use lemmy_utils::{ @@ -41,10 +46,10 @@ use url::Url; pub mod comment; pub mod community; +pub mod local_user; pub mod post; pub mod routes; pub mod site; -pub mod user; pub mod websocket; #[async_trait::async_trait(?Send)] @@ -60,11 +65,11 @@ pub trait Perform { pub(crate) async fn is_mod_or_admin( pool: &DbPool, - user_id: i32, - community_id: i32, + person_id: PersonId, + community_id: CommunityId, ) -> Result<(), LemmyError> { 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?; if !is_mod_or_admin { @@ -72,78 +77,88 @@ pub(crate) async fn is_mod_or_admin( } 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??; - if !user.admin { + +pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> { + if !local_user_view.local_user.admin { return Err(ApiError::err("not_an_admin").into()); } Ok(()) } -pub(crate) async fn get_post(post_id: i32, pool: &DbPool) -> Result { +pub(crate) async fn get_post(post_id: PostId, pool: &DbPool) -> Result { match blocking(pool, move |conn| Post::read(conn, post_id)).await? { Ok(post) => Ok(post), Err(_e) => Err(ApiError::err("couldnt_find_post").into()), } } -pub(crate) async fn get_user_from_jwt(jwt: &str, pool: &DbPool) -> Result { +pub(crate) async fn get_local_user_view_from_jwt( + jwt: &str, + pool: &DbPool, +) -> Result { let claims = match Claims::decode(&jwt) { Ok(claims) => claims.claims, Err(_e) => return Err(ApiError::err("not_logged_in").into()), }; - let user_id = claims.id; - let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??; + let local_user_id = LocalUserId(claims.local_user_id); + let local_user_view = + blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??; // Check for a site ban - if user.banned { + if local_user_view.person.banned { return Err(ApiError::err("site_ban").into()); } - Ok(user) + Ok(local_user_view) } -pub(crate) async fn get_user_from_jwt_opt( +pub(crate) async fn get_local_user_view_from_jwt_opt( jwt: &Option, pool: &DbPool, -) -> Result, LemmyError> { +) -> Result, LemmyError> { 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), } } -pub(crate) async fn get_user_safe_settings_from_jwt( +pub(crate) async fn get_local_user_settings_view_from_jwt( jwt: &str, pool: &DbPool, -) -> Result { +) -> Result { let claims = match Claims::decode(&jwt) { Ok(claims) => claims.claims, Err(_e) => return Err(ApiError::err("not_logged_in").into()), }; - let user_id = claims.id; - let user = blocking(pool, move |conn| UserSafeSettings::read(conn, user_id)).await??; + let local_user_id = LocalUserId(claims.local_user_id); + let local_user_view = blocking(pool, move |conn| { + LocalUserSettingsView::read(conn, local_user_id) + }) + .await??; // Check for a site ban - if user.banned { + if local_user_view.person.banned { return Err(ApiError::err("site_ban").into()); } - Ok(user) + 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, pool: &DbPool, -) -> Result, LemmyError> { +) -> Result, LemmyError> { 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), } } pub(crate) async fn check_community_ban( - user_id: i32, - community_id: i32, + person_id: PersonId, + community_id: CommunityId, pool: &DbPool, ) -> 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? { Err(ApiError::err("community_ban").into()) } else { @@ -165,21 +180,21 @@ 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 /// 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 /// * `pool` - the diesel db pool pub(crate) async fn collect_moderated_communities( - user_id: i32, - community_id: Option, + person_id: PersonId, + community_id: Option, pool: &DbPool, -) -> Result, LemmyError> { +) -> Result, LemmyError> { if let Some(community_id) = community_id { // 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]) } else { let ids = blocking(pool, move |conn: &'_ _| { - CommunityModerator::get_user_moderated_communities(conn, user_id) + CommunityModerator::get_person_moderated_communities(conn, person_id) }) .await??; Ok(ids) @@ -236,17 +251,17 @@ pub async fn match_websocket_operation( UserOperation::Login => do_websocket_operation::(context, id, op, data).await, UserOperation::Register => do_websocket_operation::(context, id, op, data).await, UserOperation::GetCaptcha => do_websocket_operation::(context, id, op, data).await, - UserOperation::GetUserDetails => { - do_websocket_operation::(context, id, op, data).await + UserOperation::GetPersonDetails => { + do_websocket_operation::(context, id, op, data).await } UserOperation::GetReplies => do_websocket_operation::(context, id, op, data).await, UserOperation::AddAdmin => do_websocket_operation::(context, id, op, data).await, - UserOperation::BanUser => do_websocket_operation::(context, id, op, data).await, - UserOperation::GetUserMentions => { - do_websocket_operation::(context, id, op, data).await + UserOperation::BanPerson => do_websocket_operation::(context, id, op, data).await, + UserOperation::GetPersonMentions => { + do_websocket_operation::(context, id, op, data).await } - UserOperation::MarkUserMentionAsRead => { - do_websocket_operation::(context, id, op, data).await + UserOperation::MarkPersonMentionAsRead => { + do_websocket_operation::(context, id, op, data).await } UserOperation::MarkAllAsRead => { do_websocket_operation::(context, id, op, data).await diff --git a/crates/api/src/user.rs b/crates/api/src/local_user.rs similarity index 63% rename from crates/api/src/user.rs rename to crates/api/src/local_user.rs index 93ffdfff4..e9daa8196 100644 --- a/crates/api/src/user.rs +++ b/crates/api/src/local_user.rs @@ -1,8 +1,8 @@ use crate::{ captcha_espeak_wav_base64, collect_moderated_communities, - get_user_from_jwt, - get_user_from_jwt_opt, + get_local_user_view_from_jwt, + get_local_user_view_from_jwt_opt, is_admin, password_length_check, Perform, @@ -12,7 +12,7 @@ use anyhow::Context; use bcrypt::verify; use captcha::{gen, Difficulty}; use chrono::Duration; -use lemmy_api_structs::{blocking, send_email_to_user, user::*}; +use lemmy_api_structs::{blocking, person::*, send_email_to_user}; use lemmy_apub::{ generate_apub_endpoint, generate_followers_url, @@ -27,12 +27,13 @@ use lemmy_db_queries::{ source::{ comment::Comment_, community::Community_, + local_user::LocalUser_, password_reset_request::PasswordResetRequest_, + person::Person_, + person_mention::PersonMention_, post::Post_, private_message::PrivateMessage_, site::Site_, - user::User, - user_mention::UserMention_, }, Crud, Followable, @@ -45,18 +46,21 @@ use lemmy_db_schema::{ source::{ comment::Comment, community::*, + local_user::{LocalUser, LocalUserForm}, moderator::*, password_reset_request::*, + person::*, + person_mention::*, post::Post, private_message::*, site::*, - user::*, - user_mention::*, }, + CommunityId, }; use lemmy_db_views::{ comment_report_view::CommentReportView, comment_view::CommentQueryBuilder, + local_user_view::LocalUserView, post_report_view::PostReportView, post_view::PostQueryBuilder, private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView}, @@ -64,8 +68,8 @@ use lemmy_db_views::{ use lemmy_db_views_actor::{ community_follower_view::CommunityFollowerView, community_moderator_view::CommunityModeratorView, - user_mention_view::{UserMentionQueryBuilder, UserMentionView}, - user_view::UserViewSafe, + person_mention_view::{PersonMentionQueryBuilder, PersonMentionView}, + person_view::PersonViewSafe, }; use lemmy_utils::{ apub::generate_actor_keypair, @@ -105,24 +109,28 @@ impl Perform for Login { // Fetch that username / email let username_or_email = data.username_or_email.clone(); - let user = match blocking(context.pool(), move |conn| { - User_::find_by_email_or_username(conn, &username_or_email) + let local_user_view = match blocking(context.pool(), move |conn| { + LocalUserView::find_by_email_or_name(conn, &username_or_email) }) .await? { - Ok(user) => user, + Ok(uv) => uv, Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()), }; // Verify the password - let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false); + let valid: bool = verify( + &data.password, + &local_user_view.local_user.password_encrypted, + ) + .unwrap_or(false); if !valid { return Err(ApiError::err("password_incorrect").into()); } // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt(user.id, Settings::get().hostname())?, + jwt: Claims::jwt(local_user_view.local_user.id.0, Settings::get().hostname())?, }) } } @@ -154,7 +162,7 @@ impl Perform for Register { // Check if there are admins. False if admins exist let no_admins = blocking(context.pool(), move |conn| { - UserViewSafe::admins(conn).map(|a| a.is_empty()) + PersonViewSafe::admins(conn).map(|a| a.is_empty()) }) .await??; @@ -180,58 +188,83 @@ impl Perform for Register { check_slurs(&data.username)?; - let user_keypair = generate_actor_keypair()?; + let actor_keypair = generate_actor_keypair()?; if !is_valid_username(&data.username) { return Err(ApiError::err("invalid_username").into()); } - let user_actor_id = generate_apub_endpoint(EndpointType::User, &data.username)?; + let actor_id = generate_apub_endpoint(EndpointType::Person, &data.username)?; - // Register the new user - let user_form = UserForm { + // We have to create both a person, and local_user + + // Register the new person + let person_form = PersonForm { name: data.username.to_owned(), - email: Some(data.email.to_owned()), - matrix_user_id: None, avatar: None, banner: None, - password_encrypted: data.password.to_owned(), preferred_username: None, published: None, updated: None, - admin: no_admins, - banned: Some(false), - show_nsfw: data.show_nsfw, - theme: "browser".into(), - default_sort_type: SortType::Active as i16, - default_listing_type: ListingType::Subscribed as i16, - lang: "browser".into(), - show_avatars: true, - send_notifications_to_email: false, - actor_id: Some(user_actor_id.clone()), + banned: None, + deleted: None, + actor_id: Some(actor_id.clone()), bio: None, - local: true, - private_key: Some(user_keypair.private_key), - public_key: Some(user_keypair.public_key), + local: Some(true), + private_key: Some(Some(actor_keypair.private_key)), + public_key: Some(Some(actor_keypair.public_key)), last_refreshed_at: None, - inbox_url: Some(generate_inbox_url(&user_actor_id)?), - shared_inbox_url: Some(Some(generate_shared_inbox_url(&user_actor_id)?)), + inbox_url: Some(generate_inbox_url(&actor_id)?), + shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), }; - // Create the user - let inserted_user = match blocking(context.pool(), move |conn| { - User_::register(conn, &user_form) + // insert the person + let inserted_person = match blocking(context.pool(), move |conn| { + Person::create(conn, &person_form) }) .await? { - Ok(user) => user, + Ok(u) => u, + Err(_) => { + return Err(ApiError::err("user_already_exists").into()); + } + }; + + // Create the local user + let local_user_form = LocalUserForm { + person_id: inserted_person.id, + email: Some(data.email.to_owned()), + matrix_user_id: None, + password_encrypted: data.password.to_owned(), + admin: Some(no_admins), + show_nsfw: Some(data.show_nsfw), + theme: Some("browser".into()), + default_sort_type: Some(SortType::Active as i16), + default_listing_type: Some(ListingType::Subscribed as i16), + lang: Some("browser".into()), + show_avatars: Some(true), + send_notifications_to_email: Some(false), + }; + + let inserted_local_user = match blocking(context.pool(), move |conn| { + LocalUser::register(conn, &local_user_form) + }) + .await? + { + Ok(lu) => lu, Err(e) => { let err_type = if e.to_string() - == "duplicate key value violates unique constraint \"user__email_key\"" + == "duplicate key value violates unique constraint \"local_user_email_key\"" { "email_already_exists" } else { "user_already_exists" }; + // If the local user creation errored, then delete that person + blocking(context.pool(), move |conn| { + Person::delete(&conn, inserted_person.id) + }) + .await??; + return Err(ApiError::err(err_type).into()); } }; @@ -239,44 +272,47 @@ impl Perform for Register { let main_community_keypair = generate_actor_keypair()?; // Create the main community if it doesn't exist - let main_community = - match blocking(context.pool(), move |conn| Community::read(conn, 2)).await? { - Ok(c) => c, - Err(_e) => { - let default_community_name = "main"; - let actor_id = generate_apub_endpoint(EndpointType::Community, default_community_name)?; - let community_form = CommunityForm { - name: default_community_name.to_string(), - title: "The Default Community".to_string(), - description: Some("The Default Community".to_string()), - nsfw: false, - creator_id: inserted_user.id, - removed: None, - deleted: None, - updated: None, - actor_id: Some(actor_id.to_owned()), - local: true, - private_key: Some(main_community_keypair.private_key), - public_key: Some(main_community_keypair.public_key), - last_refreshed_at: None, - published: None, - icon: None, - banner: None, - followers_url: Some(generate_followers_url(&actor_id)?), - inbox_url: Some(generate_inbox_url(&actor_id)?), - shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), - }; - blocking(context.pool(), move |conn| { - Community::create(conn, &community_form) - }) - .await?? - } - }; + let main_community = match blocking(context.pool(), move |conn| { + Community::read(conn, CommunityId(2)) + }) + .await? + { + Ok(c) => c, + Err(_e) => { + let default_community_name = "main"; + let actor_id = generate_apub_endpoint(EndpointType::Community, default_community_name)?; + let community_form = CommunityForm { + name: default_community_name.to_string(), + title: "The Default Community".to_string(), + description: Some("The Default Community".to_string()), + nsfw: false, + creator_id: inserted_person.id, + removed: None, + deleted: None, + updated: None, + actor_id: Some(actor_id.to_owned()), + local: true, + private_key: Some(main_community_keypair.private_key), + public_key: Some(main_community_keypair.public_key), + last_refreshed_at: None, + published: None, + icon: None, + banner: None, + followers_url: Some(generate_followers_url(&actor_id)?), + inbox_url: Some(generate_inbox_url(&actor_id)?), + shared_inbox_url: Some(Some(generate_shared_inbox_url(&actor_id)?)), + }; + blocking(context.pool(), move |conn| { + Community::create(conn, &community_form) + }) + .await?? + } + }; // Sign them up for main community no matter what let community_follower_form = CommunityFollowerForm { community_id: main_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, pending: false, }; @@ -289,7 +325,7 @@ impl Perform for Register { if no_admins { let community_moderator_form = CommunityModeratorForm { community_id: main_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, }; let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form); @@ -300,7 +336,7 @@ impl Perform for Register { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt(inserted_user.id, Settings::get().hostname())?, + jwt: Claims::jwt(inserted_local_user.id.0, Settings::get().hostname())?, }) } } @@ -362,7 +398,7 @@ impl Perform for SaveUserSettings { _websocket_id: Option, ) -> Result { let data: &SaveUserSettings = &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 avatar = diesel_option_overwrite_to_url(&data.avatar)?; let banner = diesel_option_overwrite_to_url(&data.banner)?; @@ -383,7 +419,8 @@ impl Perform for SaveUserSettings { } } - let user_id = user.id; + let local_user_id = local_user_view.local_user.id; + let person_id = local_user_view.person.id; let password_encrypted = match &data.new_password { Some(new_password) => { match &data.new_password_verify { @@ -398,13 +435,15 @@ impl Perform for SaveUserSettings { // Check the old password match &data.old_password { Some(old_password) => { - let valid: bool = verify(old_password, &user.password_encrypted).unwrap_or(false); + let valid: bool = + verify(old_password, &local_user_view.local_user.password_encrypted) + .unwrap_or(false); if !valid { return Err(ApiError::err("password_incorrect").into()); } let new_password = new_password.to_owned(); let user = blocking(context.pool(), move |conn| { - User_::update_password(conn, user_id, &new_password) + LocalUser::update_password(conn, local_user_id, &new_password) }) .await??; user.password_encrypted @@ -415,25 +454,48 @@ impl Perform for SaveUserSettings { None => return Err(ApiError::err("passwords_dont_match").into()), } } - None => user.password_encrypted, + None => local_user_view.local_user.password_encrypted, }; let default_listing_type = data.default_listing_type; let default_sort_type = data.default_sort_type; - let user_form = UserForm { - name: user.name, - email, - matrix_user_id, + let person_form = PersonForm { + name: local_user_view.person.name, avatar, banner, inbox_url: None, - password_encrypted, preferred_username, - published: Some(user.published), + published: None, updated: Some(naive_now()), - admin: user.admin, - banned: Some(user.banned), + banned: None, + deleted: None, + actor_id: None, + bio, + local: None, + private_key: None, + public_key: None, + last_refreshed_at: None, + shared_inbox_url: None, + }; + + let person_res = blocking(context.pool(), move |conn| { + Person::update(conn, person_id, &person_form) + }) + .await?; + let _updated_person: Person = match person_res { + Ok(p) => p, + Err(_) => { + return Err(ApiError::err("user_already_exists").into()); + } + }; + + let local_user_form = LocalUserForm { + person_id, + email, + matrix_user_id, + password_encrypted, + admin: None, show_nsfw: data.show_nsfw, theme: data.theme.to_owned(), default_sort_type, @@ -441,24 +503,17 @@ impl Perform for SaveUserSettings { lang: data.lang.to_owned(), show_avatars: data.show_avatars, send_notifications_to_email: data.send_notifications_to_email, - actor_id: Some(user.actor_id), - bio, - local: user.local, - private_key: user.private_key, - public_key: user.public_key, - last_refreshed_at: None, - shared_inbox_url: None, }; - let res = blocking(context.pool(), move |conn| { - User_::update(conn, user_id, &user_form) + let local_user_res = blocking(context.pool(), move |conn| { + LocalUser::update(conn, local_user_id, &local_user_form) }) .await?; - let updated_user: User_ = match res { - Ok(user) => user, + let updated_local_user = match local_user_res { + Ok(u) => u, Err(e) => { let err_type = if e.to_string() - == "duplicate key value violates unique constraint \"user__email_key\"" + == "duplicate key value violates unique constraint \"local_user_email_key\"" { "email_already_exists" } else { @@ -471,25 +526,25 @@ impl Perform for SaveUserSettings { // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt(updated_user.id, Settings::get().hostname())?, + jwt: Claims::jwt(updated_local_user.id.0, Settings::get().hostname())?, }) } } #[async_trait::async_trait(?Send)] -impl Perform for GetUserDetails { - type Response = GetUserDetailsResponse; +impl Perform for GetPersonDetails { + type Response = GetPersonDetailsResponse; async fn perform( &self, context: &Data, _websocket_id: Option, - ) -> Result { - let data: &GetUserDetails = &self; - let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; + ) -> Result { + let data: &GetPersonDetails = &self; + let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; - let show_nsfw = match &user { - Some(user) => user.show_nsfw, + let show_nsfw = match &local_user_view { + Some(uv) => uv.local_user.show_nsfw, None => false, }; @@ -499,26 +554,26 @@ impl Perform for GetUserDetails { .username .to_owned() .unwrap_or_else(|| "admin".to_string()); - let user_details_id = match data.user_id { + let person_details_id = match data.person_id { Some(id) => id, None => { - let user = blocking(context.pool(), move |conn| { - User_::read_from_name(conn, &username) + let person = blocking(context.pool(), move |conn| { + Person::find_by_name(conn, &username) }) .await?; - match user { - Ok(user) => user.id, + match person { + Ok(p) => p.id, Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()), } } }; - let user_id = user.map(|u| u.id); + let person_id = local_user_view.map(|uv| uv.person.id); // You don't need to return settings for the user, since this comes back with GetSite // `my_user` - let user_view = blocking(context.pool(), move |conn| { - UserViewSafe::read(conn, user_details_id) + let person_view = blocking(context.pool(), move |conn| { + PersonViewSafe::read(conn, person_details_id) }) .await??; @@ -533,12 +588,12 @@ impl Perform for GetUserDetails { .show_nsfw(show_nsfw) .saved_only(saved_only) .community_id(community_id) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit); let mut comments_query = CommentQueryBuilder::create(conn) - .my_user_id(user_id) + .my_person_id(person_id) .sort(&sort) .saved_only(saved_only) .page(page) @@ -547,8 +602,8 @@ impl Perform for GetUserDetails { // If its saved only, you don't care what creator it was // Or, if its not saved, then you only want it for that specific creator if !saved_only { - posts_query = posts_query.creator_id(user_details_id); - comments_query = comments_query.creator_id(user_details_id); + posts_query = posts_query.creator_id(person_details_id); + comments_query = comments_query.creator_id(person_details_id); } let posts = posts_query.list()?; @@ -559,22 +614,22 @@ impl Perform for GetUserDetails { .await??; let mut follows = vec![]; - if let Some(uid) = user_id { - if uid == user_details_id { + if let Some(pid) = person_id { + if pid == person_details_id { follows = blocking(context.pool(), move |conn| { - CommunityFollowerView::for_user(conn, user_details_id) + CommunityFollowerView::for_person(conn, person_details_id) }) .await??; } }; let moderates = blocking(context.pool(), move |conn| { - CommunityModeratorView::for_user(conn, user_details_id) + CommunityModeratorView::for_person(conn, person_details_id) }) .await??; // Return the jwt - Ok(GetUserDetailsResponse { - user_view, + Ok(GetPersonDetailsResponse { + person_view, follows, moderates, comments, @@ -593,22 +648,28 @@ impl Perform for AddAdmin { websocket_id: Option, ) -> Result { let data: &AddAdmin = &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?; // Make sure user is an admin - is_admin(context.pool(), user.id).await?; + is_admin(&local_user_view)?; let added = data.added; - let added_user_id = data.user_id; - let add_admin = move |conn: &'_ _| User_::add_admin(conn, added_user_id, added); - if blocking(context.pool(), add_admin).await?.is_err() { - return Err(ApiError::err("couldnt_update_user").into()); - } + let added_person_id = data.person_id; + let added_admin = match blocking(context.pool(), move |conn| { + LocalUser::add_admin(conn, added_person_id, added) + }) + .await? + { + Ok(a) => a, + Err(_) => { + return Err(ApiError::err("couldnt_update_user").into()); + } + }; // Mod tables let form = ModAddForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: added_admin.person_id, removed: Some(!data.added), }; @@ -619,13 +680,13 @@ impl Perform for AddAdmin { }) .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 .iter() - .position(|r| r.user.id == site_creator_id) + .position(|r| r.person.id == site_creator_id) .context(location_info!())?; - let creator_user = admins.remove(creator_index); - admins.insert(0, creator_user); + let creator_person = admins.remove(creator_index); + admins.insert(0, creator_person); let res = AddAdminResponse { admins }; @@ -640,24 +701,24 @@ impl Perform for AddAdmin { } #[async_trait::async_trait(?Send)] -impl Perform for BanUser { - type Response = BanUserResponse; +impl Perform for BanPerson { + type Response = BanPersonResponse; async fn perform( &self, context: &Data, websocket_id: Option, - ) -> Result { - let data: &BanUser = &self; - let user = get_user_from_jwt(&data.auth, context.pool()).await?; + ) -> Result { + let data: &BanPerson = &self; + let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; // Make sure user is an admin - is_admin(context.pool(), user.id).await?; + is_admin(&local_user_view)?; let ban = data.ban; - let banned_user_id = data.user_id; - let ban_user = move |conn: &'_ _| User_::ban_user(conn, banned_user_id, ban); - if blocking(context.pool(), ban_user).await?.is_err() { + let banned_person_id = data.person_id; + let ban_person = move |conn: &'_ _| Person::ban_person(conn, banned_person_id, ban); + if blocking(context.pool(), ban_person).await?.is_err() { return Err(ApiError::err("couldnt_update_user").into()); } @@ -665,19 +726,19 @@ impl Perform for BanUser { if data.remove_data { // Posts blocking(context.pool(), move |conn: &'_ _| { - Post::update_removed_for_creator(conn, banned_user_id, None, true) + Post::update_removed_for_creator(conn, banned_person_id, None, true) }) .await??; // Communities blocking(context.pool(), move |conn: &'_ _| { - Community::update_removed_for_creator(conn, banned_user_id, true) + Community::update_removed_for_creator(conn, banned_person_id, true) }) .await??; // Comments blocking(context.pool(), move |conn: &'_ _| { - Comment::update_removed_for_creator(conn, banned_user_id, true) + Comment::update_removed_for_creator(conn, banned_person_id, true) }) .await??; } @@ -689,8 +750,8 @@ impl Perform for BanUser { }; let form = ModBanForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: data.person_id, reason: data.reason.to_owned(), banned: Some(data.ban), expires, @@ -698,19 +759,19 @@ impl Perform for BanUser { blocking(context.pool(), move |conn| ModBan::create(conn, &form)).await??; - let user_id = data.user_id; - let user_view = blocking(context.pool(), move |conn| { - UserViewSafe::read(conn, user_id) + let person_id = data.person_id; + let person_view = blocking(context.pool(), move |conn| { + PersonViewSafe::read(conn, person_id) }) .await??; - let res = BanUserResponse { - user_view, + let res = BanPersonResponse { + person_view, banned: data.ban, }; context.chat_server().do_send(SendAllMessage { - op: UserOperation::BanUser, + op: UserOperation::BanPerson, response: res.clone(), websocket_id, }); @@ -729,20 +790,20 @@ impl Perform for GetReplies { _websocket_id: Option, ) -> Result { let data: &GetReplies = &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 sort = SortType::from_str(&data.sort)?; let page = data.page; let limit = data.limit; let unread_only = data.unread_only; - let user_id = user.id; + let person_id = local_user_view.person.id; let replies = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) .sort(&sort) .unread_only(unread_only) - .recipient_id(user_id) - .my_user_id(user_id) + .recipient_id(person_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -754,27 +815,27 @@ impl Perform for GetReplies { } #[async_trait::async_trait(?Send)] -impl Perform for GetUserMentions { - type Response = GetUserMentionsResponse; +impl Perform for GetPersonMentions { + type Response = GetPersonMentionsResponse; async fn perform( &self, context: &Data, _websocket_id: Option, - ) -> Result { - let data: &GetUserMentions = &self; - let user = get_user_from_jwt(&data.auth, context.pool()).await?; + ) -> Result { + let data: &GetPersonMentions = &self; + let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; let sort = SortType::from_str(&data.sort)?; let page = data.page; let limit = data.limit; let unread_only = data.unread_only; - let user_id = user.id; + let person_id = local_user_view.person.id; let mentions = blocking(context.pool(), move |conn| { - UserMentionQueryBuilder::create(conn) - .recipient_id(user_id) - .my_user_id(user_id) + PersonMentionQueryBuilder::create(conn) + .recipient_id(person_id) + .my_person_id(person_id) .sort(&sort) .unread_only(unread_only) .page(page) @@ -783,47 +844,50 @@ impl Perform for GetUserMentions { }) .await??; - Ok(GetUserMentionsResponse { mentions }) + Ok(GetPersonMentionsResponse { mentions }) } } #[async_trait::async_trait(?Send)] -impl Perform for MarkUserMentionAsRead { - type Response = UserMentionResponse; +impl Perform for MarkPersonMentionAsRead { + type Response = PersonMentionResponse; async fn perform( &self, context: &Data, _websocket_id: Option, - ) -> Result { - let data: &MarkUserMentionAsRead = &self; - let user = get_user_from_jwt(&data.auth, context.pool()).await?; + ) -> Result { + let data: &MarkPersonMentionAsRead = &self; + let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; - let user_mention_id = data.user_mention_id; - let read_user_mention = blocking(context.pool(), move |conn| { - UserMention::read(conn, user_mention_id) + let person_mention_id = data.person_mention_id; + let read_person_mention = blocking(context.pool(), move |conn| { + PersonMention::read(conn, person_mention_id) }) .await??; - if user.id != read_user_mention.recipient_id { + if local_user_view.person.id != read_person_mention.recipient_id { return Err(ApiError::err("couldnt_update_comment").into()); } - let user_mention_id = read_user_mention.id; + let person_mention_id = read_person_mention.id; let read = data.read; - let update_mention = move |conn: &'_ _| UserMention::update_read(conn, user_mention_id, read); + let update_mention = + move |conn: &'_ _| PersonMention::update_read(conn, person_mention_id, read); if blocking(context.pool(), update_mention).await?.is_err() { return Err(ApiError::err("couldnt_update_comment").into()); }; - let user_mention_id = read_user_mention.id; - let user_id = user.id; - let user_mention_view = blocking(context.pool(), move |conn| { - UserMentionView::read(conn, user_mention_id, Some(user_id)) + let person_mention_id = read_person_mention.id; + let person_id = local_user_view.person.id; + let person_mention_view = blocking(context.pool(), move |conn| { + PersonMentionView::read(conn, person_mention_id, Some(person_id)) }) .await??; - Ok(UserMentionResponse { user_mention_view }) + Ok(PersonMentionResponse { + person_mention_view, + }) } } @@ -837,13 +901,13 @@ impl Perform for MarkAllAsRead { _websocket_id: Option, ) -> Result { let data: &MarkAllAsRead = &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 replies = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) - .my_user_id(user_id) - .recipient_id(user_id) + .my_person_id(person_id) + .recipient_id(person_id) .unread_only(true) .page(1) .limit(999) @@ -863,8 +927,9 @@ impl Perform for MarkAllAsRead { } // Mark all user mentions as read - let update_user_mentions = move |conn: &'_ _| UserMention::mark_all_as_read(conn, user_id); - if blocking(context.pool(), update_user_mentions) + let update_person_mentions = + move |conn: &'_ _| PersonMention::mark_all_as_read(conn, person_id); + if blocking(context.pool(), update_person_mentions) .await? .is_err() { @@ -872,7 +937,7 @@ impl Perform for MarkAllAsRead { } // Mark all private_messages as read - let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, user_id); + let update_pm = move |conn: &'_ _| PrivateMessage::mark_all_as_read(conn, person_id); if blocking(context.pool(), update_pm).await?.is_err() { return Err(ApiError::err("couldnt_update_private_message").into()); } @@ -891,29 +956,33 @@ impl Perform for DeleteAccount { _websocket_id: Option, ) -> Result { let data: &DeleteAccount = &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 the password - let valid: bool = verify(&data.password, &user.password_encrypted).unwrap_or(false); + let valid: bool = verify( + &data.password, + &local_user_view.local_user.password_encrypted, + ) + .unwrap_or(false); if !valid { return Err(ApiError::err("password_incorrect").into()); } // Comments - let user_id = user.id; - let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, user_id); + let person_id = local_user_view.person.id; + let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, person_id); if blocking(context.pool(), permadelete).await?.is_err() { return Err(ApiError::err("couldnt_update_comment").into()); } // Posts - let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, user_id); + let permadelete = move |conn: &'_ _| Post::permadelete_for_creator(conn, person_id); if blocking(context.pool(), permadelete).await?.is_err() { return Err(ApiError::err("couldnt_update_post").into()); } blocking(context.pool(), move |conn| { - User_::delete_account(conn, user_id) + Person::delete_account(conn, person_id) }) .await??; @@ -936,12 +1005,12 @@ impl Perform for PasswordReset { // Fetch that email let email = data.email.clone(); - let user = match blocking(context.pool(), move |conn| { - User_::find_by_email(conn, &email) + let local_user_view = match blocking(context.pool(), move |conn| { + LocalUserView::find_by_email(conn, &email) }) .await? { - Ok(user) => user, + Ok(lu) => lu, Err(_e) => return Err(ApiError::err("couldnt_find_that_username_or_email").into()), }; @@ -950,19 +1019,19 @@ impl Perform for PasswordReset { // Insert the row let token2 = token.clone(); - let user_id = user.id; + let local_user_id = local_user_view.local_user.id; blocking(context.pool(), move |conn| { - PasswordResetRequest::create_token(conn, user_id, &token2) + PasswordResetRequest::create_token(conn, local_user_id, &token2) }) .await??; // Email the pure token to the user. // TODO no i18n support here. - let user_email = &user.email.expect("email"); - let subject = &format!("Password reset for {}", user.name); + let email = &local_user_view.local_user.email.expect("email"); + let subject = &format!("Password reset for {}", local_user_view.person.name); let hostname = &Settings::get().get_protocol_and_hostname(); - let html = &format!("

Password Reset Request for {}


Click here to reset your password", user.name, hostname, &token); - match send_email(subject, user_email, &user.name, html) { + let html = &format!("

Password Reset Request for {}


Click here to reset your password", local_user_view.person.name, hostname, &token); + match send_email(subject, email, &local_user_view.person.name, html) { Ok(_o) => _o, Err(_e) => return Err(ApiError::err(&_e).into()), }; @@ -984,8 +1053,8 @@ impl Perform for PasswordChange { // Fetch the user_id from the token let token = data.token.clone(); - let user_id = blocking(context.pool(), move |conn| { - PasswordResetRequest::read_from_token(conn, &token).map(|p| p.user_id) + let local_user_id = blocking(context.pool(), move |conn| { + PasswordResetRequest::read_from_token(conn, &token).map(|p| p.local_user_id) }) .await??; @@ -998,18 +1067,18 @@ impl Perform for PasswordChange { // Update the user with the new password let password = data.password.clone(); - let updated_user = match blocking(context.pool(), move |conn| { - User_::update_password(conn, user_id, &password) + let updated_local_user = match blocking(context.pool(), move |conn| { + LocalUser::update_password(conn, local_user_id, &password) }) .await? { - Ok(user) => user, + Ok(u) => u, Err(_e) => return Err(ApiError::err("couldnt_update_user").into()), }; // Return the jwt Ok(LoginResponse { - jwt: Claims::jwt(updated_user.id, Settings::get().hostname())?, + jwt: Claims::jwt(updated_local_user.id.0, Settings::get().hostname())?, }) } } @@ -1024,13 +1093,13 @@ impl Perform for CreatePrivateMessage { websocket_id: Option, ) -> Result { let data: &CreatePrivateMessage = &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 private_message_form = PrivateMessageForm { content: content_slurs_removed.to_owned(), - creator_id: user.id, + creator_id: local_user_view.person.id, recipient_id: data.recipient_id, deleted: None, read: None, @@ -1072,36 +1141,41 @@ impl Perform for CreatePrivateMessage { Err(_e) => return Err(ApiError::err("couldnt_create_private_message").into()), }; - updated_private_message.send_create(&user, context).await?; + updated_private_message + .send_create(&local_user_view.person, context) + .await?; - // Send notifications to the recipient - let recipient_id = data.recipient_id; - let recipient_user = - blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??; - if recipient_user.send_notifications_to_email { - send_email_to_user( - recipient_user, - "Private Message from", - "Private Message", - &content_slurs_removed, - ); - } - - let message = blocking(context.pool(), move |conn| { + let private_message_view = blocking(context.pool(), move |conn| { PrivateMessageView::read(conn, inserted_private_message.id) }) .await??; let res = PrivateMessageResponse { - private_message_view: message, + private_message_view, }; - context.chat_server().do_send(SendUserRoomMessage { - op: UserOperation::CreatePrivateMessage, - response: res.clone(), - recipient_id, - websocket_id, - }); + // Send notifications to the local recipient, if one exists + let recipient_id = data.recipient_id; + if let Ok(local_recipient) = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await? + { + send_email_to_user( + &local_recipient, + "Private Message from", + "Private Message", + &content_slurs_removed, + ); + + let local_recipient_id = local_recipient.local_user.id; + context.chat_server().do_send(SendUserRoomMessage { + op: UserOperation::CreatePrivateMessage, + response: res.clone(), + local_recipient_id, + websocket_id, + }); + } Ok(res) } @@ -1117,7 +1191,7 @@ impl Perform for EditPrivateMessage { websocket_id: Option, ) -> Result { let data: &EditPrivateMessage = &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?; // Checking permissions let private_message_id = data.private_message_id; @@ -1125,7 +1199,7 @@ impl Perform for EditPrivateMessage { PrivateMessage::read(conn, private_message_id) }) .await??; - if user.id != orig_private_message.creator_id { + if local_user_view.person.id != orig_private_message.creator_id { return Err(ApiError::err("no_private_message_edit_allowed").into()); } @@ -1142,25 +1216,35 @@ impl Perform for EditPrivateMessage { }; // Send the apub update - updated_private_message.send_update(&user, context).await?; + updated_private_message + .send_update(&local_user_view.person, context) + .await?; let private_message_id = data.private_message_id; - let message = blocking(context.pool(), move |conn| { + let private_message_view = blocking(context.pool(), move |conn| { PrivateMessageView::read(conn, private_message_id) }) .await??; - let recipient_id = message.recipient.id; let res = PrivateMessageResponse { - private_message_view: message, + private_message_view, }; - context.chat_server().do_send(SendUserRoomMessage { - op: UserOperation::EditPrivateMessage, - response: res.clone(), - recipient_id, - websocket_id, - }); + // Send notifications to the local recipient, if one exists + let recipient_id = orig_private_message.recipient_id; + if let Ok(local_recipient) = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await? + { + let local_recipient_id = local_recipient.local_user.id; + context.chat_server().do_send(SendUserRoomMessage { + op: UserOperation::EditPrivateMessage, + response: res.clone(), + local_recipient_id, + websocket_id, + }); + } Ok(res) } @@ -1176,7 +1260,7 @@ impl Perform for DeletePrivateMessage { websocket_id: Option, ) -> Result { let data: &DeletePrivateMessage = &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?; // Checking permissions let private_message_id = data.private_message_id; @@ -1184,7 +1268,7 @@ impl Perform for DeletePrivateMessage { PrivateMessage::read(conn, private_message_id) }) .await??; - if user.id != orig_private_message.creator_id { + if local_user_view.person.id != orig_private_message.creator_id { return Err(ApiError::err("no_private_message_edit_allowed").into()); } @@ -1202,30 +1286,40 @@ impl Perform for DeletePrivateMessage { // Send the apub update if data.deleted { - updated_private_message.send_delete(&user, context).await?; + updated_private_message + .send_delete(&local_user_view.person, context) + .await?; } else { updated_private_message - .send_undo_delete(&user, context) + .send_undo_delete(&local_user_view.person, context) .await?; } let private_message_id = data.private_message_id; - let message = blocking(context.pool(), move |conn| { + let private_message_view = blocking(context.pool(), move |conn| { PrivateMessageView::read(conn, private_message_id) }) .await??; - let recipient_id = message.recipient.id; let res = PrivateMessageResponse { - private_message_view: message, + private_message_view, }; - context.chat_server().do_send(SendUserRoomMessage { - op: UserOperation::DeletePrivateMessage, - response: res.clone(), - recipient_id, - websocket_id, - }); + // Send notifications to the local recipient, if one exists + let recipient_id = orig_private_message.recipient_id; + if let Ok(local_recipient) = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await? + { + let local_recipient_id = local_recipient.local_user.id; + context.chat_server().do_send(SendUserRoomMessage { + op: UserOperation::DeletePrivateMessage, + response: res.clone(), + local_recipient_id, + websocket_id, + }); + } Ok(res) } @@ -1241,7 +1335,7 @@ impl Perform for MarkPrivateMessageAsRead { websocket_id: Option, ) -> Result { let data: &MarkPrivateMessageAsRead = &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?; // Checking permissions let private_message_id = data.private_message_id; @@ -1249,7 +1343,7 @@ impl Perform for MarkPrivateMessageAsRead { PrivateMessage::read(conn, private_message_id) }) .await??; - if user.id != orig_private_message.recipient_id { + if local_user_view.person.id != orig_private_message.recipient_id { return Err(ApiError::err("couldnt_update_private_message").into()); } @@ -1266,24 +1360,31 @@ impl Perform for MarkPrivateMessageAsRead { }; // No need to send an apub update - let private_message_id = data.private_message_id; - let message = blocking(context.pool(), move |conn| { + let private_message_view = blocking(context.pool(), move |conn| { PrivateMessageView::read(conn, private_message_id) }) .await??; - let recipient_id = message.recipient.id; let res = PrivateMessageResponse { - private_message_view: message, + private_message_view, }; - context.chat_server().do_send(SendUserRoomMessage { - op: UserOperation::MarkPrivateMessageAsRead, - response: res.clone(), - recipient_id, - websocket_id, - }); + // Send notifications to the local recipient, if one exists + let recipient_id = orig_private_message.recipient_id; + if let Ok(local_recipient) = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await? + { + let local_recipient_id = local_recipient.local_user.id; + context.chat_server().do_send(SendUserRoomMessage { + op: UserOperation::MarkPrivateMessageAsRead, + response: res.clone(), + local_recipient_id, + websocket_id, + }); + } Ok(res) } @@ -1299,14 +1400,14 @@ impl Perform for GetPrivateMessages { _websocket_id: Option, ) -> Result { let data: &GetPrivateMessages = &self; - let user = get_user_from_jwt(&data.auth, context.pool()).await?; - let user_id = user.id; + let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?; + let person_id = local_user_view.person.id; let page = data.page; let limit = data.limit; let unread_only = data.unread_only; let messages = blocking(context.pool(), move |conn| { - PrivateMessageQueryBuilder::create(&conn, user_id) + PrivateMessageQueryBuilder::create(&conn, person_id) .page(page) .limit(limit) .unread_only(unread_only) @@ -1330,12 +1431,12 @@ impl Perform for GetReportCount { websocket_id: Option, ) -> Result { let data: &GetReportCount = &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_ids = - collect_moderated_communities(user_id, community_id, context.pool()).await?; + collect_moderated_communities(person_id, community_id, context.pool()).await?; let res = { if community_ids.is_empty() { @@ -1368,7 +1469,7 @@ impl Perform for GetReportCount { context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::GetReportCount, response: res.clone(), - recipient_id: user.id, + local_recipient_id: local_user_view.local_user.id, websocket_id, }); diff --git a/crates/api/src/post.rs b/crates/api/src/post.rs index 202ea30b3..9911f6722 100644 --- a/crates/api/src/post.rs +++ b/crates/api/src/post.rs @@ -2,8 +2,8 @@ use crate::{ check_community_ban, check_downvotes_enabled, collect_moderated_communities, - get_user_from_jwt, - get_user_from_jwt_opt, + get_local_user_view_from_jwt, + get_local_user_view_from_jwt_opt, is_mod_or_admin, Perform, }; @@ -60,7 +60,7 @@ impl Perform for CreatePost { websocket_id: Option, ) -> Result { 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_opt(&data.body)?; @@ -69,7 +69,7 @@ impl Perform for CreatePost { 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?; // Fetch Iframely and pictrs cached image let data_url = data.url.as_ref(); @@ -81,7 +81,7 @@ impl Perform for CreatePost { url: data_url.map(|u| u.to_owned().into()), body: data.body.to_owned(), community_id: data.community_id, - creator_id: user.id, + creator_id: local_user_view.person.id, removed: None, deleted: None, nsfw: data.nsfw, @@ -122,12 +122,14 @@ impl Perform for CreatePost { 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 let like_form = PostLikeForm { post_id: inserted_post.id, - user_id: user.id, + person_id: local_user_view.person.id, score: 1, }; @@ -136,12 +138,14 @@ impl Perform for CreatePost { 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 let inserted_post_id = inserted_post.id; 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? { @@ -171,12 +175,12 @@ impl Perform for GetPost { _websocket_id: Option, ) -> Result { let data: &GetPost = &self; - let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?; - let user_id = user.map(|u| u.id); + let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; + let person_id = local_user_view.map(|u| u.person.id); let id = data.id; let post_view = match blocking(context.pool(), move |conn| { - PostView::read(conn, id, user_id) + PostView::read(conn, id, person_id) }) .await? { @@ -187,7 +191,7 @@ impl Perform for GetPost { let id = data.id; let comments = blocking(context.pool(), move |conn| { CommentQueryBuilder::create(conn) - .my_user_id(user_id) + .my_person_id(person_id) .post_id(id) .limit(9999) .list() @@ -202,7 +206,7 @@ impl Perform for GetPost { // Necessary for the sidebar let community_view = match blocking(context.pool(), move |conn| { - CommunityView::read(conn, community_id, user_id) + CommunityView::read(conn, community_id, person_id) }) .await? { @@ -237,15 +241,15 @@ impl Perform for GetPosts { _websocket_id: Option, ) -> Result { 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 { - Some(user) => Some(user.id), + let person_id = match &local_user_view { + Some(uv) => Some(uv.person.id), None => None, }; - let show_nsfw = match &user { - Some(user) => user.show_nsfw, + let show_nsfw = match &local_user_view { + Some(uv) => uv.local_user.show_nsfw, None => false, }; @@ -263,7 +267,7 @@ impl Perform for GetPosts { .show_nsfw(show_nsfw) .community_id(community_id) .community_name(community_name) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -288,7 +292,7 @@ impl Perform for CreatePostLike { websocket_id: Option, ) -> Result { 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 check_downvotes_enabled(data.score, context.pool()).await?; @@ -297,18 +301,18 @@ impl Perform for CreatePostLike { let post_id = data.post_id; 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 { post_id: data.post_id, - user_id: user.id, + person_id: local_user_view.person.id, score: data.score, }; // Remove any likes first - let user_id = user.id; + let person_id = local_user_view.person.id; blocking(context.pool(), move |conn| { - PostLike::remove(conn, user_id, post_id) + PostLike::remove(conn, person_id, post_id) }) .await??; @@ -322,18 +326,20 @@ impl Perform for CreatePostLike { } 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 { - post.send_dislike(&user, context).await?; + post.send_dislike(&local_user_view.person, context).await?; } } 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 user_id = user.id; + let person_id = local_user_view.person.id; 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? { @@ -363,7 +369,7 @@ impl Perform for EditPost { websocket_id: Option, ) -> Result { 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_opt(&data.body)?; @@ -375,10 +381,15 @@ impl Perform for EditPost { let post_id = data.post_id; 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 - 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()); } @@ -427,11 +438,13 @@ impl Perform for EditPost { }; // 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_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??; @@ -457,15 +470,20 @@ impl Perform for DeletePost { websocket_id: Option, ) -> Result { 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 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 - 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()); } @@ -479,15 +497,19 @@ impl Perform for DeletePost { // apub updates if deleted { - updated_post.send_delete(&user, context).await?; + updated_post + .send_delete(&local_user_view.person, context) + .await?; } else { - updated_post.send_undo_delete(&user, context).await?; + updated_post + .send_undo_delete(&local_user_view.person, context) + .await?; } // Refetch the post let post_id = data.post_id; 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??; @@ -513,15 +535,25 @@ impl Perform for RemovePost { websocket_id: Option, ) -> Result { 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 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 - 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 let post_id = data.post_id; @@ -533,7 +565,7 @@ impl Perform for RemovePost { // Mod tables let form = ModRemovePostForm { - mod_user_id: user.id, + mod_person_id: local_user_view.person.id, post_id: data.post_id, removed: Some(removed), reason: data.reason.to_owned(), @@ -545,16 +577,20 @@ impl Perform for RemovePost { // apub updates if removed { - updated_post.send_remove(&user, context).await?; + updated_post + .send_remove(&local_user_view.person, context) + .await?; } else { - updated_post.send_undo_remove(&user, context).await?; + updated_post + .send_undo_remove(&local_user_view.person, context) + .await?; } // Refetch the post 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| { - PostView::read(conn, post_id, Some(user_id)) + PostView::read(conn, post_id, Some(person_id)) }) .await??; @@ -580,15 +616,25 @@ impl Perform for LockPost { websocket_id: Option, ) -> Result { 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 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 - 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 let post_id = data.post_id; @@ -600,19 +646,21 @@ impl Perform for LockPost { // Mod tables let form = ModLockPostForm { - mod_user_id: user.id, + mod_person_id: local_user_view.person.id, post_id: data.post_id, locked: Some(locked), }; blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??; // apub updates - updated_post.send_update(&user, context).await?; + updated_post + .send_update(&local_user_view.person, context) + .await?; // Refetch the post let post_id = data.post_id; 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??; @@ -638,15 +686,25 @@ impl Perform for StickyPost { websocket_id: Option, ) -> Result { 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 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 - 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 let post_id = data.post_id; @@ -658,7 +716,7 @@ impl Perform for StickyPost { // Mod tables let form = ModStickyPostForm { - mod_user_id: user.id, + mod_person_id: local_user_view.person.id, post_id: data.post_id, stickied: Some(stickied), }; @@ -669,12 +727,14 @@ impl Perform for StickyPost { // Apub updates // 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 let post_id = data.post_id; 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??; @@ -700,11 +760,11 @@ impl Perform for SavePost { _websocket_id: Option, ) -> Result { 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 { post_id: data.post_id, - user_id: user.id, + person_id: local_user_view.person.id, }; if data.save { @@ -720,9 +780,9 @@ impl Perform for SavePost { } 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| { - PostView::read(conn, post_id, Some(user_id)) + PostView::read(conn, post_id, Some(person_id)) }) .await??; @@ -741,7 +801,7 @@ impl Perform for CreatePostReport { websocket_id: Option, ) -> Result { 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 let reason = data.reason.trim(); @@ -752,17 +812,17 @@ impl Perform for CreatePostReport { 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_view = blocking(context.pool(), move |conn| { PostView::read(&conn, post_id, None) }) .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 { - creator_id: user_id, + creator_id: person_id, post_id, original_post_name: post_view.post.name, original_post_url: post_view.post.url, @@ -784,7 +844,7 @@ impl Perform for CreatePostReport { context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::CreatePostReport, response: res.clone(), - recipient_id: user.id, + local_recipient_id: local_user_view.local_user.id, websocket_id, }); @@ -810,7 +870,7 @@ impl Perform for ResolvePostReport { websocket_id: Option, ) -> Result { 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 = blocking(context.pool(), move |conn| { @@ -818,15 +878,15 @@ impl Perform for ResolvePostReport { }) .await??; - let user_id = user.id; - is_mod_or_admin(context.pool(), user_id, report.community.id).await?; + let person_id = local_user_view.person.id; + is_mod_or_admin(context.pool(), person_id, report.community.id).await?; let resolved = data.resolved; let resolve_fun = move |conn: &'_ _| { if resolved { - PostReport::resolve(conn, report_id, user_id) + PostReport::resolve(conn, report_id, person_id) } else { - PostReport::unresolve(conn, report_id, user_id) + PostReport::unresolve(conn, report_id, person_id) } }; @@ -862,12 +922,12 @@ impl Perform for ListPostReports { websocket_id: Option, ) -> Result { 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_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 limit = data.limit; @@ -885,7 +945,7 @@ impl Perform for ListPostReports { context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::ListPostReports, response: res.clone(), - recipient_id: user.id, + local_recipient_id: local_user_view.local_user.id, websocket_id, }); diff --git a/crates/api/src/routes.rs b/crates/api/src/routes.rs index a64e0bffd..6fc46ca4c 100644 --- a/crates/api/src/routes.rs +++ b/crates/api/src/routes.rs @@ -1,6 +1,6 @@ use crate::Perform; 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_websocket::{routes::chat_route, LemmyContext}; use serde::Deserialize; @@ -137,11 +137,11 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { .service( web::scope("/user") .wrap(rate_limit.message()) - .route("", web::get().to(route_get::)) - .route("/mention", web::get().to(route_get::)) + .route("", web::get().to(route_get::)) + .route("/mention", web::get().to(route_get::)) .route( "/mention/mark_as_read", - web::post().to(route_post::), + web::post().to(route_post::), ) .route("/replies", web::get().to(route_get::)) .route( @@ -150,7 +150,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { ) .route("/join", web::post().to(route_post::)) // Admin action. I don't like that it's in /user - .route("/ban", web::post().to(route_post::)) + .route("/ban", web::post().to(route_post::)) // Account actions. I don't like that they're in /user maybe /accounts .route("/login", web::post().to(route_post::)) .route("/get_captcha", web::get().to(route_get::)) diff --git a/crates/api/src/site.rs b/crates/api/src/site.rs index af9d22c41..4d561ab21 100644 --- a/crates/api/src/site.rs +++ b/crates/api/src/site.rs @@ -1,15 +1,15 @@ use crate::{ build_federated_instances, - get_user_from_jwt, - get_user_from_jwt_opt, - get_user_safe_settings_from_jwt, - get_user_safe_settings_from_jwt_opt, + get_local_user_settings_view_from_jwt, + get_local_user_settings_view_from_jwt_opt, + get_local_user_view_from_jwt, + get_local_user_view_from_jwt_opt, is_admin, Perform, }; use actix_web::web::Data; 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_db_queries::{ diesel_option_overwrite_to_url, @@ -32,7 +32,7 @@ use lemmy_db_views::{ }; use lemmy_db_views_actor::{ community_view::CommunityQueryBuilder, - user_view::{UserQueryBuilder, UserViewSafe}, + person_view::{PersonQueryBuilder, PersonViewSafe}, }; use lemmy_db_views_moderator::{ mod_add_community_view::ModAddCommunityView, @@ -74,36 +74,36 @@ impl Perform for GetModlog { let data: &GetModlog = &self; 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 limit = data.limit; 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??; 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??; 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??; 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??; 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??; 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??; @@ -111,9 +111,9 @@ impl Perform for GetModlog { let (removed_communities, banned, added) = if data.community_id.is_none() { blocking(context.pool(), move |conn| { Ok(( - ModRemoveCommunityView::list(conn, mod_user_id, page, limit)?, - ModBanView::list(conn, mod_user_id, page, limit)?, - ModAddView::list(conn, mod_user_id, page, limit)?, + ModRemoveCommunityView::list(conn, mod_person_id, page, limit)?, + ModBanView::list(conn, mod_person_id, page, limit)?, + ModAddView::list(conn, mod_person_id, page, limit)?, )) as Result<_, LemmyError> }) .await?? @@ -152,20 +152,20 @@ impl Perform for CreateSite { 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_opt(&data.description)?; // Make sure user is an admin - is_admin(context.pool(), user.id).await?; + is_admin(&local_user_view)?; let site_form = SiteForm { name: data.name.to_owned(), description: data.description.to_owned(), icon: Some(data.icon.to_owned().map(|url| url.into())), 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, open_registration: data.open_registration, enable_nsfw: data.enable_nsfw, @@ -192,13 +192,13 @@ impl Perform for EditSite { websocket_id: Option, ) -> Result { 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_opt(&data.description)?; // 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??; @@ -283,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 if let Some(site_view) = site_view.to_owned() { let site_creator_id = site_view.creator.id; // TODO investigate why this is sometimes coming back null // Maybe user_.admin isn't being set to true? - if let Some(creator_index) = admins.iter().position(|r| r.user.id == site_creator_id) { - let creator_user = admins.remove(creator_index); - admins.insert(0, creator_user); + if let Some(creator_index) = admins.iter().position(|r| r.person.id == site_creator_id) { + let creator_person = admins.remove(creator_index); + 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 .chat_server() @@ -304,7 +304,7 @@ impl Perform for GetSite { .await .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?; Ok(GetSiteResponse { @@ -335,8 +335,8 @@ impl Perform for Search { 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 user_id = user.map(|u| u.id); + let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?; + let person_id = local_user_view.map(|u| u.person.id); let type_ = SearchType::from_str(&data.type_)?; @@ -361,7 +361,7 @@ impl Perform for Search { .show_nsfw(true) .community_id(community_id) .community_name(community_name) - .my_user_id(user_id) + .my_person_id(person_id) .search_term(q) .page(page) .limit(limit) @@ -374,7 +374,7 @@ impl Perform for Search { CommentQueryBuilder::create(&conn) .sort(&sort) .search_term(q) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -386,7 +386,7 @@ impl Perform for Search { CommunityQueryBuilder::create(conn) .sort(&sort) .search_term(q) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -395,7 +395,7 @@ impl Perform for Search { } SearchType::Users => { users = blocking(context.pool(), move |conn| { - UserQueryBuilder::create(conn) + PersonQueryBuilder::create(conn) .sort(&sort) .search_term(q) .page(page) @@ -411,7 +411,7 @@ impl Perform for Search { .show_nsfw(true) .community_id(community_id) .community_name(community_name) - .my_user_id(user_id) + .my_person_id(person_id) .search_term(q) .page(page) .limit(limit) @@ -426,7 +426,7 @@ impl Perform for Search { CommentQueryBuilder::create(conn) .sort(&sort) .search_term(q) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -440,7 +440,7 @@ impl Perform for Search { CommunityQueryBuilder::create(conn) .sort(&sort) .search_term(q) - .my_user_id(user_id) + .my_person_id(person_id) .page(page) .limit(limit) .list() @@ -451,7 +451,7 @@ impl Perform for Search { let sort = SortType::from_str(&data.sort)?; users = blocking(context.pool(), move |conn| { - UserQueryBuilder::create(conn) + PersonQueryBuilder::create(conn) .sort(&sort) .search_term(q) .page(page) @@ -465,7 +465,7 @@ impl Perform for Search { PostQueryBuilder::create(conn) .sort(&sort) .show_nsfw(true) - .my_user_id(user_id) + .my_person_id(person_id) .community_id(community_id) .community_name(community_name) .url_search(q) @@ -498,18 +498,18 @@ impl Perform for TransferSite { _websocket_id: Option, ) -> Result { 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??; // 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()); } - 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); if blocking(context.pool(), transfer_site).await?.is_err() { return Err(ApiError::err("couldnt_update_site").into()); @@ -517,8 +517,8 @@ impl Perform for TransferSite { // Mod tables let form = ModAddForm { - mod_user_id: user.id, - other_user_id: data.user_id, + mod_person_id: local_user_view.person.id, + other_person_id: data.person_id, removed: Some(false), }; @@ -526,24 +526,26 @@ impl Perform for TransferSite { 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 .iter() - .position(|r| r.user.id == site_view.creator.id) + .position(|r| r.person.id == site_view.creator.id) .context(location_info!())?; - let creator_user = admins.remove(creator_index); - admins.insert(0, creator_user); + let creator_person = admins.remove(creator_index); + 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 my_user = Some(get_local_user_settings_view_from_jwt(&data.auth, context.pool()).await?); + Ok(GetSiteResponse { site_view: Some(site_view), admins, banned, online: 0, version: version::VERSION.to_string(), - my_user: Some(user), + my_user, federated_instances, }) } @@ -559,10 +561,10 @@ impl Perform for GetSiteConfig { _websocket_id: Option, ) -> Result { 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 - is_admin(context.pool(), user.id).await?; + is_admin(&local_user_view)?; let config_hjson = Settings::read_config_file()?; @@ -580,11 +582,10 @@ impl Perform for SaveSiteConfig { _websocket_id: Option, ) -> Result { 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 - let user_id = user.id; - is_admin(context.pool(), user_id).await?; + is_admin(&local_user_view)?; // 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) { diff --git a/crates/api/src/websocket.rs b/crates/api/src/websocket.rs index 58933712d..ae5ba8940 100644 --- a/crates/api/src/websocket.rs +++ b/crates/api/src/websocket.rs @@ -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 lemmy_api_structs::websocket::*; use lemmy_utils::{ConnectionId, LemmyError}; @@ -17,11 +17,11 @@ impl Perform for UserJoin { websocket_id: Option, ) -> Result { 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 { context.chat_server().do_send(JoinUserRoom { - user_id: user.id, + local_user_id: local_user_view.local_user.id, id: ws_id, }); } diff --git a/crates/api_structs/src/comment.rs b/crates/api_structs/src/comment.rs index 71c26e11d..f62c41aa4 100644 --- a/crates/api_structs/src/comment.rs +++ b/crates/api_structs/src/comment.rs @@ -1,11 +1,12 @@ +use lemmy_db_schema::{CommentId, CommunityId, LocalUserId, PostId}; use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView}; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] pub struct CreateComment { pub content: String, - pub parent_id: Option, - pub post_id: i32, + pub parent_id: Option, + pub post_id: PostId, pub form_id: Option, pub auth: String, } @@ -13,21 +14,21 @@ pub struct CreateComment { #[derive(Deserialize)] pub struct EditComment { pub content: String, - pub comment_id: i32, + pub comment_id: CommentId, pub form_id: Option, pub auth: String, } #[derive(Deserialize)] pub struct DeleteComment { - pub comment_id: i32, + pub comment_id: CommentId, pub deleted: bool, pub auth: String, } #[derive(Deserialize)] pub struct RemoveComment { - pub comment_id: i32, + pub comment_id: CommentId, pub removed: bool, pub reason: Option, pub auth: String, @@ -35,14 +36,14 @@ pub struct RemoveComment { #[derive(Deserialize)] pub struct MarkCommentAsRead { - pub comment_id: i32, + pub comment_id: CommentId, pub read: bool, pub auth: String, } #[derive(Deserialize)] pub struct SaveComment { - pub comment_id: i32, + pub comment_id: CommentId, pub save: bool, pub auth: String, } @@ -50,13 +51,13 @@ pub struct SaveComment { #[derive(Serialize, Clone)] pub struct CommentResponse { pub comment_view: CommentView, - pub recipient_ids: Vec, // TODO another way to do this? Maybe a UserMention belongs to Comment + pub recipient_ids: Vec, pub form_id: Option, // An optional front end ID, to tell which is coming back } #[derive(Deserialize)] pub struct CreateCommentLike { - pub comment_id: i32, + pub comment_id: CommentId, pub score: i16, pub auth: String, } @@ -67,7 +68,7 @@ pub struct GetComments { pub sort: String, pub page: Option, pub limit: Option, - pub community_id: Option, + pub community_id: Option, pub community_name: Option, pub auth: Option, } @@ -79,7 +80,7 @@ pub struct GetCommentsResponse { #[derive(Serialize, Deserialize)] pub struct CreateCommentReport { - pub comment_id: i32, + pub comment_id: CommentId, pub reason: String, pub auth: String, } @@ -108,7 +109,7 @@ pub struct ListCommentReports { pub page: Option, pub limit: Option, /// if no community is given, it returns reports for all communities moderated by the auth user - pub community: Option, + pub community: Option, pub auth: String, } diff --git a/crates/api_structs/src/community.rs b/crates/api_structs/src/community.rs index ee349cb04..bd0e129dc 100644 --- a/crates/api_structs/src/community.rs +++ b/crates/api_structs/src/community.rs @@ -1,14 +1,15 @@ +use lemmy_db_schema::{CommunityId, PersonId}; use lemmy_db_views_actor::{ community_follower_view::CommunityFollowerView, community_moderator_view::CommunityModeratorView, community_view::CommunityView, - user_view::UserViewSafe, + person_view::PersonViewSafe, }; use serde::{Deserialize, Serialize}; #[derive(Deserialize)] pub struct GetCommunity { - pub id: Option, + pub id: Option, pub name: Option, pub auth: Option, } @@ -52,8 +53,8 @@ pub struct ListCommunitiesResponse { #[derive(Deserialize, Clone)] pub struct BanFromCommunity { - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub ban: bool, pub remove_data: bool, pub reason: Option, @@ -63,14 +64,14 @@ pub struct BanFromCommunity { #[derive(Serialize, Clone)] pub struct BanFromCommunityResponse { - pub user_view: UserViewSafe, + pub person_view: PersonViewSafe, pub banned: bool, } #[derive(Deserialize)] pub struct AddModToCommunity { - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub added: bool, pub auth: String, } @@ -82,7 +83,7 @@ pub struct AddModToCommunityResponse { #[derive(Deserialize)] pub struct EditCommunity { - pub community_id: i32, + pub community_id: CommunityId, pub title: String, pub description: Option, pub icon: Option, @@ -93,14 +94,14 @@ pub struct EditCommunity { #[derive(Deserialize)] pub struct DeleteCommunity { - pub community_id: i32, + pub community_id: CommunityId, pub deleted: bool, pub auth: String, } #[derive(Deserialize)] pub struct RemoveCommunity { - pub community_id: i32, + pub community_id: CommunityId, pub removed: bool, pub reason: Option, pub expires: Option, @@ -109,7 +110,7 @@ pub struct RemoveCommunity { #[derive(Deserialize)] pub struct FollowCommunity { - pub community_id: i32, + pub community_id: CommunityId, pub follow: bool, pub auth: String, } @@ -126,7 +127,7 @@ pub struct GetFollowedCommunitiesResponse { #[derive(Deserialize)] pub struct TransferCommunity { - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub auth: String, } diff --git a/crates/api_structs/src/lib.rs b/crates/api_structs/src/lib.rs index 800fe6c8b..f57d7f2b4 100644 --- a/crates/api_structs/src/lib.rs +++ b/crates/api_structs/src/lib.rs @@ -1,18 +1,22 @@ pub mod comment; pub mod community; +pub mod person; pub mod post; pub mod site; -pub mod user; pub mod websocket; use diesel::PgConnection; -use lemmy_db_queries::{source::user::User, Crud, DbPool}; -use lemmy_db_schema::source::{ - comment::Comment, - post::Post, - user::User_, - user_mention::{UserMention, UserMentionForm}, +use lemmy_db_queries::{Crud, DbPool}; +use lemmy_db_schema::{ + source::{ + comment::Comment, + person::Person, + 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 log::error; use serde::{Deserialize, Serialize}; @@ -54,14 +58,13 @@ where pub async fn send_local_notifs( mentions: Vec, comment: Comment, - user: &User_, + person: Person, post: Post, pool: &DbPool, do_send_email: bool, -) -> Result, LemmyError> { - let user2 = user.clone(); +) -> Result, LemmyError> { 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?; @@ -72,40 +75,40 @@ fn do_send_local_notifs( conn: &PgConnection, mentions: &[MentionData], comment: &Comment, - user: &User_, + person: &Person, post: &Post, do_send_email: bool, -) -> Vec { +) -> Vec { let mut recipient_ids = Vec::new(); // Send the local mentions for mention in mentions .iter() - .filter(|m| m.is_local() && m.name.ne(&user.name)) + .filter(|m| m.is_local() && m.name.ne(&person.name)) .collect::>() { - 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 // 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 - recipient_ids.push(mention_user.id); + recipient_ids.push(mention_user_view.local_user.id); - let user_mention_form = UserMentionForm { - recipient_id: mention_user.id, + let user_mention_form = PersonMentionForm { + recipient_id: mention_user_view.person.id, comment_id: comment.id, read: None, }; // Allow this to fail softly, since comment edits might re-update or replace it // 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 - if do_send_email && mention_user.send_notifications_to_email { + // Send an email to those local users that have notifications on + if do_send_email { send_email_to_user( - mention_user, + &mention_user_view, "Mentioned by", - "User Mention", + "Person Mention", &comment.content, ) } @@ -116,12 +119,20 @@ fn do_send_local_notifs( match comment.parent_id { Some(parent_id) => { if let Ok(parent_comment) = Comment::read(&conn, parent_id) { - if parent_comment.creator_id != user.id { - if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) { - recipient_ids.push(parent_user.id); + // Don't send a notif to yourself + if parent_comment.creator_id != person.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 { - send_email_to_user(parent_user, "Reply from", "Comment Reply", &comment.content) + if do_send_email { + 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 None => { - if post.creator_id != user.id { - if let Ok(parent_user) = User_::read(&conn, post.creator_id) { - recipient_ids.push(parent_user.id); + if post.creator_id != person.id { + if let Ok(parent_user_view) = LocalUserView::read_person(&conn, post.creator_id) { + recipient_ids.push(parent_user_view.local_user.id); - if do_send_email && parent_user.send_notifications_to_email { - send_email_to_user(parent_user, "Reply from", "Post Reply", &comment.content) + if do_send_email { + send_email_to_user( + &parent_user_view, + "Reply from", + "Post Reply", + &comment.content, + ) } } } @@ -143,26 +159,31 @@ fn do_send_local_notifs( recipient_ids } -pub fn send_email_to_user(user: User_, subject_text: &str, body_text: &str, comment_content: &str) { - if user.banned { +pub fn send_email_to_user( + 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; } - if let Some(user_email) = user.email { + if let Some(user_email) = &local_user_view.local_user.email { let subject = &format!( "{} - {} {}", subject_text, Settings::get().hostname(), - user.name, + local_user_view.person.name, ); let html = &format!( "

{}


{} - {}

inbox", body_text, - user.name, + local_user_view.person.name, comment_content, 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, Err(e) => error!("{}", e), }; diff --git a/crates/api_structs/src/user.rs b/crates/api_structs/src/person.rs similarity index 76% rename from crates/api_structs/src/user.rs rename to crates/api_structs/src/person.rs index dcc35f06c..7767da460 100644 --- a/crates/api_structs/src/user.rs +++ b/crates/api_structs/src/person.rs @@ -6,8 +6,8 @@ use lemmy_db_views::{ use lemmy_db_views_actor::{ community_follower_view::CommunityFollowerView, community_moderator_view::CommunityModeratorView, - user_mention_view::UserMentionView, - user_view::UserViewSafe, + person_mention_view::PersonMentionView, + person_view::PersonViewSafe, }; use serde::{Deserialize, Serialize}; @@ -16,6 +16,7 @@ pub struct Login { pub username_or_email: String, pub password: String, } +use lemmy_db_schema::{CommunityId, PersonId, PersonMentionId, PrivateMessageId}; #[derive(Deserialize)] pub struct Register { @@ -45,11 +46,11 @@ pub struct CaptchaResponse { #[derive(Deserialize)] pub struct SaveUserSettings { - pub show_nsfw: bool, - pub theme: String, - pub default_sort_type: i16, - pub default_listing_type: i16, - pub lang: String, + pub show_nsfw: Option, + pub theme: Option, + pub default_sort_type: Option, + pub default_listing_type: Option, + pub lang: Option, pub avatar: Option, pub banner: Option, pub preferred_username: Option, @@ -59,8 +60,8 @@ pub struct SaveUserSettings { pub new_password: Option, pub new_password_verify: Option, pub old_password: Option, - pub show_avatars: bool, - pub send_notifications_to_email: bool, + pub show_avatars: Option, + pub send_notifications_to_email: Option, pub auth: String, } @@ -70,20 +71,20 @@ pub struct LoginResponse { } #[derive(Deserialize)] -pub struct GetUserDetails { - pub user_id: Option, +pub struct GetPersonDetails { + pub person_id: Option, pub username: Option, pub sort: String, pub page: Option, pub limit: Option, - pub community_id: Option, + pub community_id: Option, pub saved_only: bool, pub auth: Option, } #[derive(Serialize)] -pub struct GetUserDetailsResponse { - pub user_view: UserViewSafe, +pub struct GetPersonDetailsResponse { + pub person_view: PersonViewSafe, pub follows: Vec, pub moderates: Vec, pub comments: Vec, @@ -96,8 +97,8 @@ pub struct GetRepliesResponse { } #[derive(Serialize)] -pub struct GetUserMentionsResponse { - pub mentions: Vec, +pub struct GetPersonMentionsResponse { + pub mentions: Vec, } #[derive(Deserialize)] @@ -107,19 +108,19 @@ pub struct MarkAllAsRead { #[derive(Deserialize)] pub struct AddAdmin { - pub user_id: i32, + pub person_id: PersonId, pub added: bool, pub auth: String, } #[derive(Serialize, Clone)] pub struct AddAdminResponse { - pub admins: Vec, + pub admins: Vec, } #[derive(Deserialize)] -pub struct BanUser { - pub user_id: i32, +pub struct BanPerson { + pub person_id: PersonId, pub ban: bool, pub remove_data: bool, pub reason: Option, @@ -128,8 +129,8 @@ pub struct BanUser { } #[derive(Serialize, Clone)] -pub struct BanUserResponse { - pub user_view: UserViewSafe, +pub struct BanPersonResponse { + pub person_view: PersonViewSafe, pub banned: bool, } @@ -143,7 +144,7 @@ pub struct GetReplies { } #[derive(Deserialize)] -pub struct GetUserMentions { +pub struct GetPersonMentions { pub sort: String, pub page: Option, pub limit: Option, @@ -152,15 +153,15 @@ pub struct GetUserMentions { } #[derive(Deserialize)] -pub struct MarkUserMentionAsRead { - pub user_mention_id: i32, +pub struct MarkPersonMentionAsRead { + pub person_mention_id: PersonMentionId, pub read: bool, pub auth: String, } #[derive(Serialize, Clone)] -pub struct UserMentionResponse { - pub user_mention_view: UserMentionView, +pub struct PersonMentionResponse { + pub person_mention_view: PersonMentionView, } #[derive(Deserialize)] @@ -187,27 +188,27 @@ pub struct PasswordChange { #[derive(Deserialize)] pub struct CreatePrivateMessage { pub content: String, - pub recipient_id: i32, + pub recipient_id: PersonId, pub auth: String, } #[derive(Deserialize)] pub struct EditPrivateMessage { - pub private_message_id: i32, + pub private_message_id: PrivateMessageId, pub content: String, pub auth: String, } #[derive(Deserialize)] pub struct DeletePrivateMessage { - pub private_message_id: i32, + pub private_message_id: PrivateMessageId, pub deleted: bool, pub auth: String, } #[derive(Deserialize)] pub struct MarkPrivateMessageAsRead { - pub private_message_id: i32, + pub private_message_id: PrivateMessageId, pub read: bool, pub auth: String, } @@ -232,13 +233,13 @@ pub struct PrivateMessageResponse { #[derive(Serialize, Deserialize, Debug)] pub struct GetReportCount { - pub community: Option, + pub community: Option, pub auth: String, } #[derive(Serialize, Deserialize, Clone, Debug)] pub struct GetReportCountResponse { - pub community: Option, + pub community: Option, pub comment_reports: i64, pub post_reports: i64, } diff --git a/crates/api_structs/src/post.rs b/crates/api_structs/src/post.rs index 82be66170..d09911667 100644 --- a/crates/api_structs/src/post.rs +++ b/crates/api_structs/src/post.rs @@ -1,3 +1,4 @@ +use lemmy_db_schema::{CommunityId, PostId}; use lemmy_db_views::{ comment_view::CommentView, post_report_view::PostReportView, @@ -16,7 +17,7 @@ pub struct CreatePost { pub url: Option, pub body: Option, pub nsfw: bool, - pub community_id: i32, + pub community_id: CommunityId, pub auth: String, } @@ -27,7 +28,7 @@ pub struct PostResponse { #[derive(Deserialize)] pub struct GetPost { - pub id: i32, + pub id: PostId, pub auth: Option, } @@ -46,7 +47,7 @@ pub struct GetPosts { pub sort: String, pub page: Option, pub limit: Option, - pub community_id: Option, + pub community_id: Option, pub community_name: Option, pub auth: Option, } @@ -58,14 +59,14 @@ pub struct GetPostsResponse { #[derive(Deserialize)] pub struct CreatePostLike { - pub post_id: i32, + pub post_id: PostId, pub score: i16, pub auth: String, } #[derive(Deserialize)] pub struct EditPost { - pub post_id: i32, + pub post_id: PostId, pub name: String, pub url: Option, pub body: Option, @@ -75,14 +76,14 @@ pub struct EditPost { #[derive(Deserialize)] pub struct DeletePost { - pub post_id: i32, + pub post_id: PostId, pub deleted: bool, pub auth: String, } #[derive(Deserialize)] pub struct RemovePost { - pub post_id: i32, + pub post_id: PostId, pub removed: bool, pub reason: Option, pub auth: String, @@ -90,28 +91,28 @@ pub struct RemovePost { #[derive(Deserialize)] pub struct LockPost { - pub post_id: i32, + pub post_id: PostId, pub locked: bool, pub auth: String, } #[derive(Deserialize)] pub struct StickyPost { - pub post_id: i32, + pub post_id: PostId, pub stickied: bool, pub auth: String, } #[derive(Deserialize)] pub struct SavePost { - pub post_id: i32, + pub post_id: PostId, pub save: bool, pub auth: String, } #[derive(Serialize, Deserialize)] pub struct CreatePostReport { - pub post_id: i32, + pub post_id: PostId, pub reason: String, pub auth: String, } @@ -138,7 +139,7 @@ pub struct ResolvePostReportResponse { pub struct ListPostReports { pub page: Option, pub limit: Option, - pub community: Option, + pub community: Option, pub auth: String, } diff --git a/crates/api_structs/src/site.rs b/crates/api_structs/src/site.rs index 9f69e63bc..090fa8f5b 100644 --- a/crates/api_structs/src/site.rs +++ b/crates/api_structs/src/site.rs @@ -1,6 +1,11 @@ -use lemmy_db_schema::source::user::UserSafeSettings; -use lemmy_db_views::{comment_view::CommentView, post_view::PostView, site_view::SiteView}; -use lemmy_db_views_actor::{community_view::CommunityView, user_view::UserViewSafe}; +use lemmy_db_schema::{CommunityId, PersonId}; +use lemmy_db_views::{ + 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::{ mod_add_community_view::ModAddCommunityView, mod_add_view::ModAddView, @@ -19,7 +24,7 @@ use url::Url; pub struct Search { pub q: String, pub type_: String, - pub community_id: Option, + pub community_id: Option, pub community_name: Option, pub sort: String, pub page: Option, @@ -33,13 +38,13 @@ pub struct SearchResponse { pub comments: Vec, pub posts: Vec, pub communities: Vec, - pub users: Vec, + pub users: Vec, } #[derive(Deserialize)] pub struct GetModlog { - pub mod_user_id: Option, - pub community_id: Option, + pub mod_person_id: Option, + pub community_id: Option, pub page: Option, pub limit: Option, } @@ -94,17 +99,17 @@ pub struct SiteResponse { #[derive(Serialize)] pub struct GetSiteResponse { pub site_view: Option, // Because the site might not be set up yet - pub admins: Vec, - pub banned: Vec, + pub admins: Vec, + pub banned: Vec, pub online: usize, pub version: String, - pub my_user: Option, + pub my_user: Option, pub federated_instances: Option, // Federation may be disabled } #[derive(Deserialize)] pub struct TransferSite { - pub user_id: i32, + pub person_id: PersonId, pub auth: String, } diff --git a/crates/api_structs/src/websocket.rs b/crates/api_structs/src/websocket.rs index c3ae14653..c64a56c04 100644 --- a/crates/api_structs/src/websocket.rs +++ b/crates/api_structs/src/websocket.rs @@ -1,3 +1,4 @@ +use lemmy_db_schema::{CommunityId, PostId}; use serde::{Deserialize, Serialize}; #[derive(Deserialize, Debug)] @@ -12,7 +13,7 @@ pub struct UserJoinResponse { #[derive(Deserialize, Debug)] pub struct CommunityJoin { - pub community_id: i32, + pub community_id: CommunityId, } #[derive(Serialize, Clone)] @@ -22,7 +23,7 @@ pub struct CommunityJoinResponse { #[derive(Deserialize, Debug)] pub struct ModJoin { - pub community_id: i32, + pub community_id: CommunityId, } #[derive(Serialize, Clone)] @@ -32,7 +33,7 @@ pub struct ModJoinResponse { #[derive(Deserialize, Debug)] pub struct PostJoin { - pub post_id: i32, + pub post_id: PostId, } #[derive(Serialize, Clone)] diff --git a/crates/apub/src/activities/receive/comment.rs b/crates/apub/src/activities/receive/comment.rs index 07f25eec7..95b51d648 100644 --- a/crates/apub/src/activities/receive/comment.rs +++ b/crates/apub/src/activities/receive/comment.rs @@ -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::{ activity::{ActorAndObjectRefExt, Create, Dislike, Like, Update}, base::ExtendsExt, @@ -19,11 +19,12 @@ pub(crate) async fn receive_create_comment( context: &LemmyContext, request_counter: &mut i32, ) -> 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!())?)? .context(location_info!())?; - let comment = Comment::from_apub(¬e, context, user.actor_id(), request_counter, false).await?; + let comment = + Comment::from_apub(¬e, context, person.actor_id(), request_counter, false).await?; let post_id = comment.post_id; let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -33,8 +34,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 // anyway. let mentions = scrape_text_for_mentions(&comment.content); - let recipient_ids = - send_local_notifs(mentions, comment.clone(), &user, post, context.pool(), true).await?; + let recipient_ids = send_local_notifs( + mentions, + comment.clone(), + person, + post, + context.pool(), + true, + ) + .await?; // Refetch the view let comment_view = blocking(context.pool(), move |conn| { @@ -64,9 +72,10 @@ pub(crate) async fn receive_update_comment( ) -> Result<(), LemmyError> { let note = NoteExt::from_any_base(update.object().to_owned().one().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, false).await?; + let comment = + Comment::from_apub(¬e, context, person.actor_id(), request_counter, false).await?; let comment_id = comment.id; let post_id = comment.post_id; @@ -74,7 +83,7 @@ pub(crate) async fn receive_update_comment( let mentions = scrape_text_for_mentions(&comment.content); 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 let comment_view = blocking(context.pool(), move |conn| { @@ -103,18 +112,18 @@ pub(crate) async fn receive_like_comment( context: &LemmyContext, request_counter: &mut i32, ) -> 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 like_form = CommentLikeForm { comment_id, post_id: comment.post_id, - user_id: user.id, + person_id: person.id, score: 1, }; - let user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - CommentLike::remove(conn, user_id, comment_id)?; + CommentLike::remove(conn, person_id, comment_id)?; CommentLike::like(conn, &like_form) }) .await??; @@ -148,18 +157,18 @@ pub(crate) async fn receive_dislike_comment( context: &LemmyContext, request_counter: &mut i32, ) -> 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 like_form = CommentLikeForm { comment_id, post_id: comment.post_id, - user_id: user.id, + person_id: person.id, score: -1, }; - let user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - CommentLike::remove(conn, user_id, comment_id)?; + CommentLike::remove(conn, person_id, comment_id)?; CommentLike::like(conn, &like_form) }) .await??; diff --git a/crates/apub/src/activities/receive/comment_undo.rs b/crates/apub/src/activities/receive/comment_undo.rs index 702717155..22594f338 100644 --- a/crates/apub/src/activities/receive/comment_undo.rs +++ b/crates/apub/src/activities/receive/comment_undo.rs @@ -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 lemmy_api_structs::{blocking, comment::CommentResponse}; use lemmy_db_queries::{source::comment::Comment_, Likeable}; @@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_comment( context: &LemmyContext, request_counter: &mut i32, ) -> 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 user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - CommentLike::remove(conn, user_id, comment_id) + CommentLike::remove(conn, person_id, comment_id) }) .await??; @@ -51,12 +51,12 @@ pub(crate) async fn receive_undo_dislike_comment( context: &LemmyContext, request_counter: &mut i32, ) -> 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 user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - CommentLike::remove(conn, user_id, comment_id) + CommentLike::remove(conn, person_id, comment_id) }) .await??; diff --git a/crates/apub/src/activities/receive/mod.rs b/crates/apub/src/activities/receive/mod.rs index a03e1ef52..1d5fcc300 100644 --- a/crates/apub/src/activities/receive/mod.rs +++ b/crates/apub/src/activities/receive/mod.rs @@ -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::{ activity::{ActorAndObjectRef, ActorAndObjectRefExt}, base::{AsBase, BaseExt}, error::DomainError, }; 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_websocket::LemmyContext; use log::debug; @@ -28,18 +28,18 @@ where Err(anyhow!("Activity not supported").into()) } -/// Reads the actor field of an activity and returns the corresponding `User_`. -pub(crate) async fn get_actor_as_user( +/// Reads the actor field of an activity and returns the corresponding `Person`. +pub(crate) async fn get_actor_as_person( activity: &T, context: &LemmyContext, request_counter: &mut i32, -) -> Result +) -> Result where T: AsBase + ActorAndObjectRef, { let actor = activity.actor()?; - let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?; - get_or_fetch_and_upsert_user(&user_uri, context, request_counter).await + let person_uri = actor.as_single_xsd_any_uri().context(location_info!())?; + 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 diff --git a/crates/apub/src/activities/receive/post.rs b/crates/apub/src/activities/receive/post.rs index 631f9933b..2473c2c95 100644 --- a/crates/apub/src/activities/receive/post.rs +++ b/crates/apub/src/activities/receive/post.rs @@ -1,5 +1,5 @@ use crate::{ - activities::receive::get_actor_as_user, + activities::receive::get_actor_as_person, inbox::receive_for_community::verify_mod_activity, objects::FromApub, ActorType, @@ -28,11 +28,11 @@ pub(crate) async fn receive_create_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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!())?)? .context(location_info!())?; - let post = Post::from_apub(&page, context, user.actor_id(), request_counter, false).await?; + let post = Post::from_apub(&page, context, person.actor_id(), request_counter, false).await?; // Refetch the view let post_id = post.id; @@ -58,7 +58,7 @@ pub(crate) async fn receive_update_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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!())?)? .context(location_info!())?; @@ -91,7 +91,7 @@ pub(crate) async fn receive_update_post( let post = Post::from_apub( &page, context, - user.actor_id(), + person.actor_id(), request_counter, mod_action_allowed, ) @@ -121,17 +121,17 @@ pub(crate) async fn receive_like_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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 like_form = PostLikeForm { post_id, - user_id: user.id, + person_id: person.id, score: 1, }; - let user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - PostLike::remove(conn, user_id, post_id)?; + PostLike::remove(conn, person_id, post_id)?; PostLike::like(conn, &like_form) }) .await??; @@ -159,17 +159,17 @@ pub(crate) async fn receive_dislike_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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 like_form = PostLikeForm { post_id, - user_id: user.id, + person_id: person.id, score: -1, }; - let user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - PostLike::remove(conn, user_id, post_id)?; + PostLike::remove(conn, person_id, post_id)?; PostLike::like(conn, &like_form) }) .await??; diff --git a/crates/apub/src/activities/receive/post_undo.rs b/crates/apub/src/activities/receive/post_undo.rs index 312010a9e..67cc20df7 100644 --- a/crates/apub/src/activities/receive/post_undo.rs +++ b/crates/apub/src/activities/receive/post_undo.rs @@ -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 lemmy_api_structs::{blocking, post::PostResponse}; use lemmy_db_queries::{source::post::Post_, Likeable}; @@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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 user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - PostLike::remove(conn, user_id, post_id) + PostLike::remove(conn, person_id, post_id) }) .await??; @@ -45,12 +45,12 @@ pub(crate) async fn receive_undo_dislike_post( context: &LemmyContext, request_counter: &mut i32, ) -> 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 user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - PostLike::remove(conn, user_id, post_id) + PostLike::remove(conn, person_id, post_id) }) .await??; diff --git a/crates/apub/src/activities/receive/private_message.rs b/crates/apub/src/activities/receive/private_message.rs index b20494cf9..04954b718 100644 --- a/crates/apub/src/activities/receive/private_message.rs +++ b/crates/apub/src/activities/receive/private_message.rs @@ -1,7 +1,7 @@ use crate::{ activities::receive::verify_activity_domains_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, objects::FromApub, NoteExt, @@ -13,10 +13,10 @@ use activitystreams::{ public, }; 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_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_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation}; use url::Url; @@ -50,12 +50,19 @@ pub(crate) async fn receive_create_private_message( private_message_view: message, }; + // Send notifications to the local recipient, if one exists 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 { op: UserOperation::CreatePrivateMessage, response: res, - recipient_id, + local_recipient_id, 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 local_recipient_id = blocking(context.pool(), move |conn| { + LocalUserView::read_person(conn, recipient_id) + }) + .await?? + .local_user + .id; context.chat_server().do_send(SendUserRoomMessage { op: UserOperation::EditPrivateMessage, response: res, - recipient_id, + local_recipient_id, websocket_id: None, }); @@ -123,11 +136,19 @@ pub(crate) async fn receive_delete_private_message( let res = PrivateMessageResponse { private_message_view: message, }; + 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 { op: UserOperation::EditPrivateMessage, response: res, - recipient_id, + local_recipient_id, websocket_id: None, }); @@ -160,11 +181,19 @@ pub(crate) async fn receive_undo_delete_private_message( let res = PrivateMessageResponse { private_message_view: message, }; + 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 { op: UserOperation::EditPrivateMessage, response: res, - recipient_id, + local_recipient_id, websocket_id: None, }); @@ -181,19 +210,19 @@ where { let to_and_cc = get_activity_to_and_cc(activity); 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()) { return Err(anyhow!("Private message cant be public").into()); } - let user_id = activity + let person_id = activity .actor()? .to_owned() .single_xsd_any_uri() .context(location_info!())?; - check_is_apub_id_valid(&user_id)?; - // check that the sender is a user, not a community - get_or_fetch_and_upsert_user(&user_id, &context, request_counter).await?; + check_is_apub_id_valid(&person_id)?; + // check that the sender is a person, not a community + get_or_fetch_and_upsert_person(&person_id, &context, request_counter).await?; Ok(()) } diff --git a/crates/apub/src/activities/send/comment.rs b/crates/apub/src/activities/send/comment.rs index ac7e884a9..867e45e9f 100644 --- a/crates/apub/src/activities/send/comment.rs +++ b/crates/apub/src/activities/send/comment.rs @@ -2,7 +2,7 @@ use crate::{ activities::send::generate_activity_id, activity_queue::{send_comment_mentions, send_to_community}, extensions::context::lemmy_context, - fetcher::user::get_or_fetch_and_upsert_user, + fetcher::person::get_or_fetch_and_upsert_person, objects::ToApub, ActorType, ApubLikeableType, @@ -28,7 +28,7 @@ use anyhow::anyhow; use itertools::Itertools; use lemmy_api_structs::{blocking, WebFingerResponse}; 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::{ request::{retry, RecvError}, settings::structs::Settings, @@ -44,8 +44,8 @@ use url::Url; #[async_trait::async_trait(?Send)] impl ApubObjectType for Comment { /// Send out information about a newly created comment, to the followers of the community and - /// mentioned users. - async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + /// mentioned persons. + async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> { let note = self.to_apub(context.pool()).await?; 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 - /// users. - async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> { + /// persons. + async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> { let note = self.to_apub(context.pool()).await?; let post_id = self.post_id; @@ -109,7 +109,7 @@ impl ApubObjectType for Comment { 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 = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -135,7 +135,7 @@ impl ApubObjectType for Comment { async fn send_undo_delete( &self, - creator: &User_, + creator: &Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let post_id = self.post_id; @@ -173,7 +173,7 @@ impl ApubObjectType for Comment { 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 = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -197,7 +197,11 @@ impl ApubObjectType for Comment { 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 = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -236,7 +240,7 @@ impl ApubObjectType for Comment { #[async_trait::async_trait(?Send)] 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 = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -260,7 +264,7 @@ impl ApubLikeableType for Comment { 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 = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??; @@ -286,7 +290,7 @@ impl ApubLikeableType for Comment { async fn send_undo_like( &self, - creator: &User_, + creator: &Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let post_id = self.post_id; @@ -342,7 +346,7 @@ impl MentionsAndAddresses { /// This takes a comment, and builds a list of to_addresses, inboxes, /// 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( comment: &Comment, community: &Community, @@ -356,7 +360,7 @@ async fn collect_non_local_mentions( // Add the mention tag 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) .into_iter() // Filter only the non-local ones @@ -369,8 +373,8 @@ async fn collect_non_local_mentions( debug!("mention actor_id: {}", actor_id); 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?; - inboxes.push(mention_user.get_shared_inbox_or_inbox_url()); + let mention_person = get_or_fetch_and_upsert_person(&actor_id, context, &mut 0).await?; + inboxes.push(mention_person.get_shared_inbox_or_inbox_url()); let mut mention_tag = Mention::new(); 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. -async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result { +async fn get_comment_parent_creator( + pool: &DbPool, + comment: &Comment, +) -> Result { let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id { let parent_comment = 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??; 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. async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result { let fetch_url = format!( diff --git a/crates/apub/src/activities/send/community.rs b/crates/apub/src/activities/send/community.rs index 84d2fcedd..80f0a42c8 100644 --- a/crates/apub/src/activities/send/community.rs +++ b/crates/apub/src/activities/send/community.rs @@ -3,8 +3,9 @@ use crate::{ activity_queue::{send_activity_single_dest, send_to_community, send_to_community_followers}, check_is_apub_id_valid, extensions::context::lemmy_context, - fetcher::user::get_or_fetch_and_upsert_user, + fetcher::person::get_or_fetch_and_upsert_person, generate_moderators_url, + insert_activity, ActorType, CommunityType, }; @@ -29,9 +30,9 @@ use anyhow::Context; use itertools::Itertools; use lemmy_api_structs::blocking; 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_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 url::Url; @@ -61,7 +62,7 @@ impl ActorType for Community { #[async_trait::async_trait(?Send)] impl CommunityType for Community { - /// 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( &self, follow: Follow, @@ -71,7 +72,7 @@ impl CommunityType for Community { .actor()? .as_single_xsd_any_uri() .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( self.actor_id.to_owned().into_inner(), @@ -80,9 +81,9 @@ impl CommunityType for Community { accept .set_many_contexts(lemmy_context()?) .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(()) } @@ -155,11 +156,20 @@ impl CommunityType for Community { /// Wraps an activity sent to the community in an announce, and then sends the announce to all /// 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( &self, activity: AnyBase, context: &LemmyContext, ) -> 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); announce .set_many_contexts(lemmy_context()?) @@ -195,8 +205,8 @@ impl CommunityType for Community { async fn send_add_mod( &self, - actor: &User_, - added_mod: User_, + actor: &Person, + added_mod: Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let mut add = Add::new( @@ -216,8 +226,8 @@ impl CommunityType for Community { async fn send_remove_mod( &self, - actor: &User_, - removed_mod: User_, + actor: &Person, + removed_mod: Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let mut remove = Remove::new( diff --git a/crates/apub/src/activities/send/mod.rs b/crates/apub/src/activities/send/mod.rs index 80660044d..10dd8a263 100644 --- a/crates/apub/src/activities/send/mod.rs +++ b/crates/apub/src/activities/send/mod.rs @@ -3,10 +3,10 @@ use url::{ParseError, Url}; use uuid::Uuid; pub(crate) mod comment; -pub mod community; +pub(crate) mod community; +pub(crate) mod person; pub(crate) mod post; pub(crate) mod private_message; -pub(crate) mod user; /// Generate a unique ID for an activity, in the format: /// `http(s)://example.com/receive/create/202daf0a-1489-45df-8d2e-c8a3173fed36` diff --git a/crates/apub/src/activities/send/user.rs b/crates/apub/src/activities/send/person.rs similarity index 94% rename from crates/apub/src/activities/send/user.rs rename to crates/apub/src/activities/send/person.rs index a0778c086..9560c2fbc 100644 --- a/crates/apub/src/activities/send/user.rs +++ b/crates/apub/src/activities/send/person.rs @@ -18,14 +18,14 @@ use lemmy_api_structs::blocking; use lemmy_db_queries::{ApubObject, Followable}; use lemmy_db_schema::source::{ community::{Community, CommunityFollower, CommunityFollowerForm}, - user::User_, + person::Person, }; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use url::Url; #[async_trait::async_trait(?Send)] -impl ActorType for User_ { +impl ActorType for Person { fn is_local(&self) -> bool { self.local } @@ -51,8 +51,8 @@ impl ActorType for User_ { } #[async_trait::async_trait(?Send)] -impl UserType for User_ { - /// As a given local user, send out a follow request to a remote community. +impl UserType for Person { + /// As a given local person, send out a follow request to a remote community. async fn send_follow( &self, follow_actor_id: &Url, @@ -66,7 +66,7 @@ impl UserType for User_ { let community_follower_form = CommunityFollowerForm { community_id: community.id, - user_id: self.id, + person_id: self.id, pending: true, }; blocking(&context.pool(), move |conn| { diff --git a/crates/apub/src/activities/send/post.rs b/crates/apub/src/activities/send/post.rs index 44f5b895f..4d3bb9d1b 100644 --- a/crates/apub/src/activities/send/post.rs +++ b/crates/apub/src/activities/send/post.rs @@ -23,14 +23,14 @@ use activitystreams::{ }; use lemmy_api_structs::blocking; 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_websocket::LemmyContext; #[async_trait::async_trait(?Send)] impl ApubObjectType for Post { /// 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 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. - 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 community_id = self.community_id; @@ -77,7 +77,7 @@ impl ApubObjectType for Post { 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 = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -100,7 +100,7 @@ impl ApubObjectType for Post { async fn send_undo_delete( &self, - creator: &User_, + creator: &Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let community_id = self.community_id; @@ -134,7 +134,7 @@ impl ApubObjectType for Post { 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 = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -155,7 +155,11 @@ impl ApubObjectType for Post { 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 = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -190,7 +194,7 @@ impl ApubObjectType for Post { #[async_trait::async_trait(?Send)] 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 = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -211,7 +215,7 @@ impl ApubLikeableType for Post { 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 = blocking(context.pool(), move |conn| { Community::read(conn, community_id) @@ -234,7 +238,7 @@ impl ApubLikeableType for Post { async fn send_undo_like( &self, - creator: &User_, + creator: &Person, context: &LemmyContext, ) -> Result<(), LemmyError> { let community_id = self.community_id; diff --git a/crates/apub/src/activities/send/private_message.rs b/crates/apub/src/activities/send/private_message.rs index 322eee5f7..92d818ab9 100644 --- a/crates/apub/src/activities/send/private_message.rs +++ b/crates/apub/src/activities/send/private_message.rs @@ -18,18 +18,19 @@ use activitystreams::{ }; use lemmy_api_structs::blocking; 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_websocket::LemmyContext; #[async_trait::async_trait(?Send)] impl ApubObjectType for PrivateMessage { /// 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 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( 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. - 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 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( creator.actor_id.to_owned().into_inner(), @@ -65,9 +67,10 @@ impl ApubObjectType for PrivateMessage { 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 = 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( creator.actor_id.to_owned().into_inner(), @@ -84,11 +87,12 @@ impl ApubObjectType for PrivateMessage { async fn send_undo_delete( &self, - creator: &User_, + creator: &Person, context: &LemmyContext, ) -> Result<(), LemmyError> { 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( creator.actor_id.to_owned().into_inner(), @@ -113,13 +117,13 @@ impl ApubObjectType for PrivateMessage { Ok(()) } - async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> { + async fn send_remove(&self, _mod_: &Person, _context: &LemmyContext) -> Result<(), LemmyError> { unimplemented!() } async fn send_undo_remove( &self, - _mod_: &User_, + _mod_: &Person, _context: &LemmyContext, ) -> Result<(), LemmyError> { unimplemented!() diff --git a/crates/apub/src/activity_queue.rs b/crates/apub/src/activity_queue.rs index 9cdc38864..b1913b4b1 100644 --- a/crates/apub/src/activity_queue.rs +++ b/crates/apub/src/activity_queue.rs @@ -22,7 +22,7 @@ use background_jobs::{ }; use itertools::Itertools; 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_websocket::LemmyContext; use log::{debug, warn}; @@ -113,7 +113,7 @@ where 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 /// * `creator` the creator of the activity @@ -121,7 +121,7 @@ where /// pub(crate) async fn send_to_community( activity: T, - creator: &User_, + creator: &Person, community: &Community, context: &LemmyContext, ) -> Result<(), LemmyError> @@ -158,13 +158,13 @@ where 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 -/// * `mentions` list of inboxes of users which are mentioned in the comment +/// * `creator` person who created the comment +/// * `mentions` list of inboxes of persons which are mentioned in the comment /// * `activity` either a `Create/Note` or `Update/Note` pub(crate) async fn send_comment_mentions( - creator: &User_, + creator: &Person, mentions: Vec, activity: T, context: &LemmyContext, diff --git a/crates/apub/src/extensions/signatures.rs b/crates/apub/src/extensions/signatures.rs index ebbf9a0a4..a9b4cfbdf 100644 --- a/crates/apub/src/extensions/signatures.rs +++ b/crates/apub/src/extensions/signatures.rs @@ -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 #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/crates/apub/src/fetcher/community.rs b/crates/apub/src/fetcher/community.rs index 4ae98be6d..2fd5ed255 100644 --- a/crates/apub/src/fetcher/community.rs +++ b/crates/apub/src/fetcher/community.rs @@ -1,6 +1,6 @@ use crate::{ fetcher::{fetch::fetch_remote_object, is_deleted, should_refetch_actor}, - inbox::user_inbox::receive_announce, + inbox::person_inbox::receive_announce, objects::FromApub, GroupExt, }; diff --git a/crates/apub/src/fetcher/mod.rs b/crates/apub/src/fetcher/mod.rs index 593b163fa..234a929b9 100644 --- a/crates/apub/src/fetcher/mod.rs +++ b/crates/apub/src/fetcher/mod.rs @@ -1,14 +1,14 @@ pub(crate) mod community; mod fetch; pub(crate) mod objects; +pub(crate) mod person; pub mod search; -pub(crate) mod user; use crate::{ fetcher::{ community::get_or_fetch_and_upsert_community, fetch::FetchError, - user::get_or_fetch_and_upsert_user, + person::get_or_fetch_and_upsert_person, }, ActorType, }; @@ -37,8 +37,8 @@ where false } -/// Get a remote actor from its apub ID (either a user or a community). Thin wrapper around -/// `get_or_fetch_and_upsert_user()` and `get_or_fetch_and_upsert_community()`. +/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around +/// `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. /// 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 actor: Box = match community { 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) } diff --git a/crates/apub/src/fetcher/user.rs b/crates/apub/src/fetcher/person.rs similarity index 64% rename from crates/apub/src/fetcher/user.rs rename to crates/apub/src/fetcher/person.rs index 7f998ac75..3788163b8 100644 --- a/crates/apub/src/fetcher/user.rs +++ b/crates/apub/src/fetcher/person.rs @@ -6,47 +6,47 @@ use crate::{ use anyhow::anyhow; use diesel::result::Error::NotFound; use lemmy_api_structs::blocking; -use lemmy_db_queries::{source::user::User, ApubObject}; -use lemmy_db_schema::source::user::User_; +use lemmy_db_queries::{source::person::Person_, ApubObject}; +use lemmy_db_schema::source::person::Person; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use log::debug; 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. /// 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, context: &LemmyContext, recursion_counter: &mut i32, -) -> Result { +) -> Result { let apub_id_owned = apub_id.to_owned(); - let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, &apub_id_owned.into()) + let person = blocking(context.pool(), move |conn| { + Person::read_from_apub_id(conn, &apub_id_owned.into()) }) .await?; - match user { + match person { // If its older than a day, re-fetch it 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 = fetch_remote_object::(context.client(), apub_id, recursion_counter).await; if is_deleted(&person) { - // TODO: use User_::update_deleted() once implemented + // TODO: use Person::update_deleted() once implemented blocking(context.pool(), move |conn| { - User_::delete_account(conn, u.id) + Person::delete_account(conn, u.id) }) .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() { return Ok(u); } - let user = User_::from_apub( + let person = Person::from_apub( &person?, context, apub_id.to_owned(), @@ -55,21 +55,21 @@ pub(crate) async fn get_or_fetch_and_upsert_user( ) .await?; - let user_id = user.id; + let person_id = person.id; blocking(context.pool(), move |conn| { - User_::mark_as_updated(conn, user_id) + Person::mark_as_updated(conn, person_id) }) .await??; - Ok(user) + Ok(person) } Ok(u) => Ok(u), Err(NotFound {}) => { - debug!("Fetching and creating remote user: {}", apub_id); + debug!("Fetching and creating remote person: {}", apub_id); let person = fetch_remote_object::(context.client(), apub_id, recursion_counter).await?; - let user = User_::from_apub( + let person = Person::from_apub( &person, context, apub_id.to_owned(), @@ -78,7 +78,7 @@ pub(crate) async fn get_or_fetch_and_upsert_user( ) .await?; - Ok(user) + Ok(person) } Err(e) => Err(e.into()), } diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 10f4ac5d2..230442972 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -2,7 +2,7 @@ use crate::{ fetcher::{ fetch::fetch_remote_object, get_or_fetch_and_upsert_community, - get_or_fetch_and_upsert_user, + get_or_fetch_and_upsert_person, is_deleted, }, find_object_by_id, @@ -20,21 +20,21 @@ use lemmy_db_queries::{ source::{ comment::Comment_, community::Community_, + person::Person_, post::Post_, private_message::PrivateMessage_, - user::User, }, SearchType, }; use lemmy_db_schema::source::{ comment::Comment, community::Community, + person::Person, post::Post, private_message::PrivateMessage, - user::User_, }; 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_websocket::LemmyContext; use log::debug; @@ -66,7 +66,7 @@ pub async fn search_by_apub_id( debug!("Search for {}", query); let split = query.split('@').collect::>(); - // User type will look like ['', username, instance] + // Person type will look like ['', username, instance] // Community will look like [!community, instance] let (name, instance) = if split.len() == 3 { (format!("/u/{}", split[1]), split[2]) @@ -122,13 +122,13 @@ async fn build_response( match fetch_response { 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![ blocking(context.pool(), move |conn| { - UserViewSafe::read(conn, user.id) + PersonViewSafe::read(conn, person.id) }) .await??, ]; @@ -182,10 +182,10 @@ async fn delete_object_locally(query_url: &Url, context: &LemmyContext) -> Resul }) .await??; } - Object::User(u) => { + Object::Person(u) => { // TODO: implement update_deleted() for user, move it to ApubObject trait blocking(context.pool(), move |conn| { - User_::delete_account(conn, u.id) + Person::delete_account(conn, u.id) }) .await??; } diff --git a/crates/apub/src/http/comment.rs b/crates/apub/src/http/comment.rs index ee777fff9..3071445bd 100644 --- a/crates/apub/src/http/comment.rs +++ b/crates/apub/src/http/comment.rs @@ -6,7 +6,7 @@ use actix_web::{body::Body, web, web::Path, HttpResponse}; use diesel::result::Error::NotFound; use lemmy_api_structs::blocking; 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_websocket::LemmyContext; use serde::Deserialize; @@ -21,7 +21,7 @@ pub(crate) async fn get_apub_comment( info: Path, context: web::Data, ) -> Result, LemmyError> { - let id = info.comment_id.parse::()?; + let id = CommentId(info.comment_id.parse::()?); let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??; if !comment.local { return Err(NotFound.into()); diff --git a/crates/apub/src/http/mod.rs b/crates/apub/src/http/mod.rs index b343a6e8d..8702bb5f7 100644 --- a/crates/apub/src/http/mod.rs +++ b/crates/apub/src/http/mod.rs @@ -11,8 +11,8 @@ use url::Url; pub mod comment; pub mod community; +pub mod person; pub mod post; -pub mod user; /// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub /// headers. diff --git a/crates/apub/src/http/user.rs b/crates/apub/src/http/person.rs similarity index 53% rename from crates/apub/src/http/user.rs rename to crates/apub/src/http/person.rs index dcb73e3b0..d523d6412 100644 --- a/crates/apub/src/http/user.rs +++ b/crates/apub/src/http/person.rs @@ -10,69 +10,69 @@ use activitystreams::{ }; use actix_web::{body::Body, web, HttpResponse}; use lemmy_api_structs::blocking; -use lemmy_db_queries::source::user::User; -use lemmy_db_schema::source::user::User_; +use lemmy_db_queries::source::person::Person_; +use lemmy_db_schema::source::person::Person; use lemmy_utils::LemmyError; use lemmy_websocket::LemmyContext; use serde::Deserialize; use url::Url; #[derive(Deserialize)] -pub(crate) struct UserQuery { +pub struct PersonQuery { user_name: String, } -/// Return the ActivityPub json representation of a local user over HTTP. -pub(crate) async fn get_apub_user_http( - info: web::Path, +/// Return the ActivityPub json representation of a local person over HTTP. +pub(crate) async fn get_apub_person_http( + info: web::Path, context: web::Data, ) -> Result, LemmyError> { let user_name = info.into_inner().user_name; - // TODO: this needs to be able to read deleted users, so that it can send tombstones - let user = blocking(context.pool(), move |conn| { - User_::find_by_email_or_username(conn, &user_name) + // TODO: this needs to be able to read deleted persons, so that it can send tombstones + let person = blocking(context.pool(), move |conn| { + Person::find_by_name(conn, &user_name) }) .await??; - if !user.deleted { - let apub = user.to_apub(context.pool()).await?; + if !person.deleted { + let apub = person.to_apub(context.pool()).await?; Ok(create_apub_response(&apub)) } else { - Ok(create_apub_tombstone_response(&user.to_tombstone()?)) + Ok(create_apub_tombstone_response(&person.to_tombstone()?)) } } -pub(crate) async fn get_apub_user_outbox( - info: web::Path, +pub(crate) async fn get_apub_person_outbox( + info: web::Path, context: web::Data, ) -> Result, LemmyError> { - let user = blocking(context.pool(), move |conn| { - User_::read_from_name(&conn, &info.user_name) + let person = blocking(context.pool(), move |conn| { + Person::find_by_name(&conn, &info.user_name) }) .await??; - // TODO: populate the user outbox + // TODO: populate the person outbox let mut collection = OrderedCollection::new(); collection .set_many_items(Vec::::new()) .set_many_contexts(lemmy_context()?) - .set_id(user.get_outbox_url()?) + .set_id(person.get_outbox_url()?) .set_total_items(0_u64); Ok(create_apub_response(&collection)) } -pub(crate) async fn get_apub_user_inbox( - info: web::Path, +pub(crate) async fn get_apub_person_inbox( + info: web::Path, context: web::Data, ) -> Result, LemmyError> { - let user = blocking(context.pool(), move |conn| { - User_::read_from_name(&conn, &info.user_name) + let person = blocking(context.pool(), move |conn| { + Person::find_by_name(&conn, &info.user_name) }) .await??; let mut collection = OrderedCollection::new(); collection - .set_id(user.inbox_url.into()) + .set_id(person.inbox_url.into()) .set_many_contexts(lemmy_context()?); Ok(create_apub_response(&collection)) } diff --git a/crates/apub/src/http/post.rs b/crates/apub/src/http/post.rs index 1b5589a0f..03218b68f 100644 --- a/crates/apub/src/http/post.rs +++ b/crates/apub/src/http/post.rs @@ -6,7 +6,7 @@ use actix_web::{body::Body, web, HttpResponse}; use diesel::result::Error::NotFound; use lemmy_api_structs::blocking; 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_websocket::LemmyContext; use serde::Deserialize; @@ -21,7 +21,7 @@ pub(crate) async fn get_apub_post( info: web::Path, context: web::Data, ) -> Result, LemmyError> { - let id = info.post_id.parse::()?; + let id = PostId(info.post_id.parse::()?); let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??; if !post.local { return Err(NotFound.into()); diff --git a/crates/apub/src/inbox/community_inbox.rs b/crates/apub/src/inbox/community_inbox.rs index cd1c775bd..e59201990 100644 --- a/crates/apub/src/inbox/community_inbox.rs +++ b/crates/apub/src/inbox/community_inbox.rs @@ -31,11 +31,14 @@ use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::{anyhow, Context}; use lemmy_api_structs::blocking; use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable}; -use lemmy_db_schema::source::{ - community::{Community, CommunityFollower, CommunityFollowerForm}, - user::User_, +use lemmy_db_schema::{ + source::{ + 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_websocket::LemmyContext; use log::info; @@ -47,8 +50,8 @@ use url::Url; #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)] #[serde(rename_all = "PascalCase")] pub enum CommunityValidTypes { - Follow, // follow request from a user - Undo, // unfollow from a user + Follow, // follow request from a person + Undo, // unfollow from a person Create, // create post or comment Update, // update post or comment Like, // upvote post or comment @@ -117,21 +120,21 @@ pub(crate) async fn community_receive_message( context: &LemmyContext, request_counter: &mut i32, ) -> Result { - // 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. let actor_id = actor.actor_id(); - let user = blocking(&context.pool(), move |conn| { - User_::read_from_apub_id(&conn, &actor_id.into()) + let person = blocking(&context.pool(), move |conn| { + Person::read_from_apub_id(&conn, &actor_id.into()) }) .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 actor_url = actor.actor_id(); let activity_kind = activity.kind().context(location_info!())?; let do_announce = match activity_kind { CommunityValidTypes::Follow => { - handle_follow(any_base.clone(), user, &to_community, &context).await?; + handle_follow(any_base.clone(), person, &to_community, &context).await?; false } CommunityValidTypes::Undo => { @@ -186,20 +189,20 @@ pub(crate) async fn community_receive_message( 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. async fn handle_follow( activity: AnyBase, - user: User_, + person: Person, community: &Community, context: &LemmyContext, ) -> Result { 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 { community_id: community.id, - user_id: user.id, + person_id: person.id, pending: false, }; @@ -234,27 +237,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( activity: AnyBase, - user_url: Url, + person_url: Url, community: &Community, context: &LemmyContext, ) -> Result<(), LemmyError> { 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 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| { - User_::read_from_apub_id(&conn, &user_url.into()) + let person = blocking(&context.pool(), move |conn| { + Person::read_from_apub_id(&conn, &person_url.into()) }) .await??; let community_follower_form = CommunityFollowerForm { community_id: community.id, - user_id: user.id, + person_id: person.id, pending: false, }; @@ -268,17 +271,18 @@ async fn handle_undo_follow( } pub(crate) async fn check_community_or_site_ban( - user: &User_, - community_id: i32, + person: &Person, + community_id: CommunityId, pool: &DbPool, ) -> Result<(), LemmyError> { - if user.banned { - return Err(anyhow!("User is banned from site").into()); + if person.banned { + return Err(anyhow!("Person is banned from site").into()); } - let user_id = user.id; - let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok(); + let person_id = person.id; + let is_banned = + move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok(); 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(()) diff --git a/crates/apub/src/inbox/mod.rs b/crates/apub/src/inbox/mod.rs index ea884183c..4fb1732d3 100644 --- a/crates/apub/src/inbox/mod.rs +++ b/crates/apub/src/inbox/mod.rs @@ -18,7 +18,7 @@ use lemmy_db_queries::{ ApubObject, 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_websocket::LemmyContext; use serde::Serialize; @@ -26,9 +26,9 @@ use std::fmt::Debug; use url::Url; pub mod community_inbox; +pub mod person_inbox; pub(crate) mod receive_for_community; pub mod shared_inbox; -pub mod user_inbox; pub(crate) fn get_activity_id(activity: &T, creator_uri: &Url) -> Result where @@ -119,17 +119,17 @@ where } /// 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], pool: &DbPool, ) -> Result { for url in to_and_cc { let url = url.to_owned(); - let user = blocking(&pool, move |conn| { - User_::read_from_apub_id(&conn, &url.into()) + let person = blocking(&pool, move |conn| { + Person::read_from_apub_id(&conn, &url.into()) }) .await?; - if let Ok(u) = user { + if let Ok(u) = person { if u.local { return Ok(true); } diff --git a/crates/apub/src/inbox/user_inbox.rs b/crates/apub/src/inbox/person_inbox.rs similarity index 88% rename from crates/apub/src/inbox/user_inbox.rs rename to crates/apub/src/inbox/person_inbox.rs index 7ddb83368..1778ea00f 100644 --- a/crates/apub/src/inbox/user_inbox.rs +++ b/crates/apub/src/inbox/person_inbox.rs @@ -25,7 +25,7 @@ use crate::{ inbox_verify_http_signature, is_activity_already_known, is_addressed_to_community_followers, - is_addressed_to_local_user, + is_addressed_to_local_person, receive_for_community::{ receive_add_for_community, receive_create_for_community, @@ -50,11 +50,11 @@ use actix_web::{web, HttpRequest, HttpResponse}; use anyhow::{anyhow, Context}; use diesel::NotFound; 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::{ community::{Community, CommunityFollower}, + person::Person, private_message::PrivateMessage, - user::User_, }; use lemmy_utils::{location_info, LemmyError}; use lemmy_websocket::LemmyContext; @@ -64,10 +64,10 @@ use std::fmt::Debug; use strum_macros::EnumString; use url::Url; -/// Allowed activities for user inbox. +/// Allowed activities for person inbox. #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)] #[serde(rename_all = "PascalCase")] -pub enum UserValidTypes { +pub enum PersonValidTypes { Accept, // community accepted our follow request Create, // create private message Update, // edit private message @@ -77,12 +77,12 @@ pub enum UserValidTypes { Announce, // post, comment or vote in community } -pub type UserAcceptedActivities = ActorAndObject; +pub type PersonAcceptedActivities = ActorAndObject; -/// Handler for all incoming activities to user inboxes. -pub async fn user_inbox( +/// Handler for all incoming activities to person inboxes. +pub async fn person_inbox( request: HttpRequest, - input: web::Json, + input: web::Json, path: web::Path, context: web::Data, ) -> Result { @@ -99,29 +99,29 @@ pub async fn user_inbox( // Check if the activity is actually meant for us let username = path.into_inner(); - let user = blocking(&context.pool(), move |conn| { - User_::read_from_name(&conn, &username) + let person = blocking(&context.pool(), move |conn| { + Person::find_by_name(&conn, &username) }) .await??; let to_and_cc = get_activity_to_and_cc(&activity); // TODO: we should also accept activities that are sent to community followers - if !to_and_cc.contains(&&user.actor_id()) { - return Err(anyhow!("Activity delivered to wrong user").into()); + if !to_and_cc.contains(&&person.actor_id()) { + return Err(anyhow!("Activity delivered to wrong person").into()); } assert_activity_not_local(&activity)?; insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?; debug!( - "User {} received activity {:?} from {}", - user.name, + "Person {} received activity {:?} from {}", + person.name, &activity.id_unchecked(), &actor.actor_id() ); - user_receive_message( + person_receive_message( activity.clone(), - Some(user.clone()), + Some(person.clone()), actor.as_ref(), &context, request_counter, @@ -130,43 +130,43 @@ pub async fn user_inbox( } /// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete -pub(crate) async fn user_receive_message( - activity: UserAcceptedActivities, - to_user: Option, +pub(crate) async fn person_receive_message( + activity: PersonAcceptedActivities, + to_person: Option, actor: &dyn ActorType, context: &LemmyContext, request_counter: &mut i32, ) -> Result { - is_for_user_inbox(context, &activity).await?; + is_for_person_inbox(context, &activity).await?; let any_base = activity.clone().into_any_base()?; let kind = activity.kind().context(location_info!())?; let actor_url = actor.actor_id(); match kind { - UserValidTypes::Accept => { + PersonValidTypes::Accept => { receive_accept( &context, any_base, actor, - to_user.expect("user provided"), + to_person.expect("person provided"), request_counter, ) .await?; } - UserValidTypes::Announce => { + PersonValidTypes::Announce => { receive_announce(&context, any_base, actor, request_counter).await? } - UserValidTypes::Create => { + PersonValidTypes::Create => { receive_create(&context, any_base, actor_url, request_counter).await? } - UserValidTypes::Update => { + PersonValidTypes::Update => { receive_update(&context, any_base, actor_url, request_counter).await? } - UserValidTypes::Delete => { + PersonValidTypes::Delete => { receive_delete(context, any_base, &actor_url, request_counter).await? } - UserValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?, - UserValidTypes::Remove => receive_remove(context, any_base, &actor_url).await?, + PersonValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?, + PersonValidTypes::Remove => receive_remove(context, any_base, &actor_url).await?, }; // TODO: would be logical to move websocket notification code here @@ -174,16 +174,16 @@ pub(crate) async fn user_receive_message( Ok(HttpResponse::Ok().finish()) } -/// Returns true if the activity is addressed directly to one or more local users, or if it is -/// addressed to the followers collection of a remote community, and at least one local user follows +/// 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 person follows /// it. -async fn is_for_user_inbox( +async fn is_for_person_inbox( context: &LemmyContext, - activity: &UserAcceptedActivities, + activity: &PersonAcceptedActivities, ) -> Result<(), LemmyError> { let to_and_cc = get_activity_to_and_cc(activity); - // Check if it is addressed directly to any local user - if is_addressed_to_local_user(&to_and_cc, context.pool()).await? { + // Check if it is addressed directly to any local person + if is_addressed_to_local_person(&to_and_cc, context.pool()).await? { return Ok(()); } @@ -206,7 +206,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. @@ -214,7 +214,7 @@ async fn receive_accept( context: &LemmyContext, activity: AnyBase, actor: &dyn ActorType, - user: User_, + person: Person, request_counter: &mut i32, ) -> Result<(), LemmyError> { let accept = Accept::from_any_base(activity)?.context(location_info!())?; @@ -222,7 +222,7 @@ async fn receive_accept( let object = accept.object().to_owned().one().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 .actor()? @@ -234,10 +234,10 @@ async fn receive_accept( get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?; 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 blocking(&context.pool(), move |conn| { - CommunityFollower::follow_accepted(conn, community_id, user_id) + CommunityFollower::follow_accepted(conn, community_id, person_id) }) .await??; diff --git a/crates/apub/src/inbox/receive_for_community.rs b/crates/apub/src/inbox/receive_for_community.rs index cd8f32bbc..b099434a8 100644 --- a/crates/apub/src/inbox/receive_for_community.rs +++ b/crates/apub/src/inbox/receive_for_community.rs @@ -33,7 +33,7 @@ use crate::{ }, fetcher::{ objects::{get_or_fetch_and_insert_comment, get_or_fetch_and_insert_post}, - user::get_or_fetch_and_upsert_user, + person::get_or_fetch_and_upsert_person, }, find_object_by_id, find_post_or_comment_by_id, @@ -69,8 +69,8 @@ use lemmy_db_queries::{source::community::CommunityModerator_, ApubObject, Crud, use lemmy_db_schema::{ source::{ community::{Community, CommunityModerator, CommunityModeratorForm}, + person::Person, site::Site, - user::User_, }, DbUrl, }; @@ -87,7 +87,7 @@ enum PageOrNote { } /// 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 pub(in crate::inbox) async fn receive_create_for_community( @@ -235,10 +235,10 @@ pub(in crate::inbox) async fn receive_remove_for_community( .object() .as_single_xsd_any_uri() .context(location_info!())?; - let remove_mod = get_or_fetch_and_upsert_user(&remove_mod, context, request_counter).await?; + let remove_mod = get_or_fetch_and_upsert_person(&remove_mod, context, request_counter).await?; let form = CommunityModeratorForm { community_id: community.id, - user_id: remove_mod.id, + person_id: remove_mod.id, }; blocking(context.pool(), move |conn| { CommunityModerator::leave(conn, &form) @@ -399,19 +399,19 @@ pub(in crate::inbox) async fn receive_add_for_community( .object() .as_single_xsd_any_uri() .context(location_info!())?; - let new_mod = get_or_fetch_and_upsert_user(&new_mod, context, request_counter).await?; + let new_mod = get_or_fetch_and_upsert_person(&new_mod, context, request_counter).await?; // If we had to refetch the community while parsing the activity, then the new mod has already // been added. Skip it here as it would result in a duplicate key error. let new_mod_id = new_mod.id; let moderated_communities = blocking(context.pool(), move |conn| { - CommunityModerator::get_user_moderated_communities(conn, new_mod_id) + CommunityModerator::get_person_moderated_communities(conn, new_mod_id) }) .await??; if !moderated_communities.contains(&community.id) { let form = CommunityModeratorForm { community_id: community.id, - user_id: new_mod.id, + person_id: new_mod.id, }; blocking(context.pool(), move |conn| { CommunityModerator::join(conn, &form) @@ -513,7 +513,7 @@ where .context(location_info!())? .to_owned(); let actor = blocking(&context.pool(), move |conn| { - User_::read_from_apub_id(&conn, &actor.into()) + Person::read_from_apub_id(&conn, &actor.into()) }) .await??; @@ -607,7 +607,7 @@ where Object::Post(p) => p.ap_id.into_inner(), Object::Comment(c) => c.ap_id.into_inner(), Object::Community(c) => c.actor_id(), - Object::User(u) => u.actor_id(), + Object::Person(p) => p.actor_id(), Object::PrivateMessage(p) => p.ap_id.into_inner(), }; if actor_id.domain() != original_id.domain() { diff --git a/crates/apub/src/inbox/shared_inbox.rs b/crates/apub/src/inbox/shared_inbox.rs index ae40b8914..c8076c201 100644 --- a/crates/apub/src/inbox/shared_inbox.rs +++ b/crates/apub/src/inbox/shared_inbox.rs @@ -7,8 +7,8 @@ use crate::{ inbox_verify_http_signature, is_activity_already_known, is_addressed_to_community_followers, - is_addressed_to_local_user, - user_inbox::{user_receive_message, UserAcceptedActivities}, + is_addressed_to_local_person, + person_inbox::{person_receive_message, PersonAcceptedActivities}, }, insert_activity, }; @@ -70,9 +70,9 @@ pub async fn shared_inbox( let mut res: Option = None; 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. - // 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. - // 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 // notifications. let community = extract_local_community_from_destinations(&to_and_cc, context.pool()).await?; @@ -89,13 +89,13 @@ pub async fn shared_inbox( ) .await?, ); - } else if is_addressed_to_local_user(&to_and_cc, context.pool()).await? { - let user_activity = UserAcceptedActivities::from_any_base(activity_any_base.clone())? + } else if is_addressed_to_local_person(&to_and_cc, context.pool()).await? { + let person_activity = PersonAcceptedActivities::from_any_base(activity_any_base.clone())? .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 - user_receive_message( - user_activity, + person_receive_message( + person_activity, None, actor.as_ref(), &context, @@ -106,11 +106,11 @@ pub async fn shared_inbox( .await? .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!())?; res = Some( - user_receive_message( - user_activity, + person_receive_message( + person_activity, None, actor.as_ref(), &context, diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index ec5c6d943..74d4cbef3 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -17,7 +17,7 @@ use crate::extensions::{ }; use activitystreams::{ activity::Follow, - actor::{ApActor, Group, Person}, + actor, base::AnyBase, object::{ApObject, Note, Page}, }; @@ -31,9 +31,9 @@ use lemmy_db_schema::{ activity::Activity, comment::Comment, community::Community, + person::{Person as DbPerson, Person}, post::Post, private_message::PrivateMessage, - user::User_, }, DbUrl, }; @@ -44,9 +44,9 @@ use std::net::IpAddr; use url::{ParseError, Url}; /// Activitystreams type for community -type GroupExt = Ext2>, GroupExtension, PublicKeyExtension>; -/// Activitystreams type for user -type PersonExt = Ext1>, PublicKeyExtension>; +type GroupExt = Ext2>, GroupExtension, PublicKeyExtension>; +/// Activitystreams type for person +type PersonExt = Ext1>, PublicKeyExtension>; /// Activitystreams type for post type PageExt = Ext1, PageExtension>; type NoteExt = ApObject; @@ -121,27 +121,41 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> { /// and actors in Lemmy. #[async_trait::async_trait(?Send)] pub trait ApubObjectType { - async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; - async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; - async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; + async fn send_create(&self, creator: &DbPerson, 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( &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, ) -> 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)] pub trait ApubLikeableType { - async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; - async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>; - async fn send_undo_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: &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. #[async_trait::async_trait(?Send)] pub trait ActorType { @@ -198,14 +212,14 @@ pub trait CommunityType { async fn send_add_mod( &self, - actor: &User_, - added_mod: User_, + actor: &Person, + added_mod: Person, context: &LemmyContext, ) -> Result<(), LemmyError>; async fn send_remove_mod( &self, - actor: &User_, - removed_mod: User_, + actor: &Person, + removed_mod: Person, context: &LemmyContext, ) -> Result<(), LemmyError>; } @@ -226,7 +240,7 @@ pub trait UserType { pub enum EndpointType { Community, - User, + Person, Post, Comment, PrivateMessage, @@ -239,7 +253,7 @@ pub fn generate_apub_endpoint( ) -> Result { let point = match endpoint_type { EndpointType::Community => "c", - EndpointType::User => "u", + EndpointType::Person => "u", EndpointType::Post => "post", EndpointType::Comment => "comment", EndpointType::PrivateMessage => "private_message", @@ -338,11 +352,11 @@ pub(crate) async fn find_post_or_comment_by_id( #[derive(Debug)] pub(crate) enum Object { - Comment(Comment), - Post(Post), - Community(Community), - User(User_), - PrivateMessage(PrivateMessage), + Comment(Box), + Post(Box), + Community(Box), + Person(Box), + PrivateMessage(Box), } pub(crate) async fn find_object_by_id( @@ -352,18 +366,18 @@ pub(crate) async fn find_object_by_id( let ap_id = apub_id.clone(); if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await { return Ok(match pc { - PostOrComment::Post(p) => Object::Post(*p), - PostOrComment::Comment(c) => Object::Comment(*c), + PostOrComment::Post(p) => Object::Post(Box::new(*p)), + PostOrComment::Comment(c) => Object::Comment(Box::new(*c)), }); } let ap_id = apub_id.clone(); - let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, &ap_id.into()) + let person = blocking(context.pool(), move |conn| { + DbPerson::read_from_apub_id(conn, &ap_id.into()) }) .await?; - if let Ok(u) = user { - return Ok(Object::User(u)); + if let Ok(u) = person { + return Ok(Object::Person(Box::new(u))); } let ap_id = apub_id.clone(); @@ -372,7 +386,7 @@ pub(crate) async fn find_object_by_id( }) .await?; 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| { @@ -380,7 +394,7 @@ pub(crate) async fn find_object_by_id( }) .await?; if let Ok(pm) = private_message { - return Ok(Object::PrivateMessage(pm)); + return Ok(Object::PrivateMessage(Box::new(pm))); } Err(NotFound.into()) diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 63f5d9e2c..536190f03 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -6,7 +6,7 @@ use crate::{ check_object_for_community_or_site_ban, create_tombstone, get_object_from_apub, - get_or_fetch_and_upsert_user, + get_or_fetch_and_upsert_person, get_source_markdown_value, set_content_and_source, FromApub, @@ -23,10 +23,13 @@ use activitystreams::{ use anyhow::{anyhow, Context}; use lemmy_api_structs::blocking; use lemmy_db_queries::{Crud, DbPool}; -use lemmy_db_schema::source::{ - comment::{Comment, CommentForm}, - post::Post, - user::User_, +use lemmy_db_schema::{ + source::{ + comment::{Comment, CommentForm}, + person::Person, + post::Post, + }, + CommentId, }; use lemmy_utils::{ location_info, @@ -44,7 +47,7 @@ impl ToApub for Comment { let mut comment = ApObject::new(Note::new()); 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 = blocking(pool, move |conn| Post::read(conn, post_id)).await??; @@ -143,7 +146,8 @@ impl FromApubToForm for CommentForm { .as_single_xsd_any_uri() .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 .in_reply_to() @@ -160,7 +164,7 @@ impl FromApubToForm for CommentForm { // The 2nd item, if it exists, is the parent comment apub_id // For deeply nested comments, FromApub automatically gets called recursively - let parent_id: Option = match in_reply_tos.next() { + let parent_id: Option = match in_reply_tos.next() { Some(parent_comment_uri) => { let parent_comment_ap_id = &parent_comment_uri?; let parent_comment = diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 73cca5c71..ae941a805 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -1,6 +1,6 @@ use crate::{ extensions::{context::lemmy_context, group_extensions::GroupExtension}, - fetcher::{community::fetch_community_mods, user::get_or_fetch_and_upsert_user}, + fetcher::{community::fetch_community_mods, person::get_or_fetch_and_upsert_person}, generate_moderators_url, objects::{ check_object_domain, @@ -129,7 +129,7 @@ impl FromApub for Community { if !new_moderators.contains(&&mod_user.moderator.actor_id.clone().into()) { let community_moderator_form = CommunityModeratorForm { community_id: mod_user.community.id, - user_id: mod_user.moderator.id, + person_id: mod_user.moderator.id, }; blocking(context.pool(), move |conn| { CommunityModerator::leave(conn, &community_moderator_form) @@ -140,7 +140,7 @@ impl FromApub for Community { // Add new mods to database which have been added to moderators collection for mod_uri in new_moderators { - let mod_user = get_or_fetch_and_upsert_user(&mod_uri, context, request_counter).await?; + let mod_user = get_or_fetch_and_upsert_person(&mod_uri, context, request_counter).await?; let current_mod_uris: Vec = current_moderators .clone() .iter() @@ -149,7 +149,7 @@ impl FromApub for Community { if !current_mod_uris.contains(&mod_user.actor_id) { let community_moderator_form = CommunityModeratorForm { community_id: community.id, - user_id: mod_user.id, + person_id: mod_user.id, }; blocking(context.pool(), move |conn| { CommunityModerator::join(conn, &community_moderator_form) @@ -174,7 +174,7 @@ impl FromApubToForm for CommunityForm { let moderator_uris = fetch_community_mods(context, group, request_counter).await?; let creator_uri = moderator_uris.first().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 .inner .preferred_username() diff --git a/crates/apub/src/objects/mod.rs b/crates/apub/src/objects/mod.rs index 78095e747..800b9dea1 100644 --- a/crates/apub/src/objects/mod.rs +++ b/crates/apub/src/objects/mod.rs @@ -1,6 +1,6 @@ use crate::{ 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, }; use activitystreams::{ @@ -14,7 +14,7 @@ use chrono::NaiveDateTime; use diesel::result::Error::NotFound; use lemmy_api_structs::blocking; use lemmy_db_queries::{ApubObject, Crud, DbPool}; -use lemmy_db_schema::{source::community::Community, DbUrl}; +use lemmy_db_schema::{source::community::Community, CommunityId, DbUrl}; use lemmy_utils::{ location_info, settings::structs::Settings, @@ -26,9 +26,9 @@ use url::Url; pub(crate) mod comment; pub(crate) mod community; +pub(crate) mod person; pub(crate) mod post; pub(crate) mod private_message; -pub(crate) mod user; /// Trait for converting an object or actor into the respective ActivityPub type. #[async_trait::async_trait(?Send)] @@ -173,7 +173,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 /// with the same ActivityPub ID already exists in the database, it is returned directly. Otherwise /// the apub object is parsed, inserted and returned. -pub(in crate::objects) async fn get_object_from_apub( +pub(in crate::objects) async fn get_object_from_apub( from: &From, context: &LemmyContext, expected_domain: Url, @@ -182,7 +182,7 @@ pub(in crate::objects) async fn get_object_from_apub( ) -> Result where From: BaseExt, - To: ApubObject + Crud + Send + 'static, + To: ApubObject + Crud + Send + 'static, ToForm: FromApubToForm + Send + 'static, { let object_id = from.id_unchecked().context(location_info!())?.to_owned(); @@ -214,20 +214,20 @@ where pub(in crate::objects) async fn check_object_for_community_or_site_ban( object: &T, - community_id: i32, + community_id: CommunityId, context: &LemmyContext, request_counter: &mut i32, ) -> Result<(), LemmyError> where T: ObjectExt, { - let user_id = object + let person_id = object .attributed_to() .context(location_info!())? .as_single_xsd_any_uri() .context(location_info!())?; - let user = get_or_fetch_and_upsert_user(user_id, context, request_counter).await?; - check_community_or_site_ban(&user, community_id, context.pool()).await + let person = get_or_fetch_and_upsert_person(person_id, context, request_counter).await?; + check_community_or_site_ban(&person, community_id, context.pool()).await } pub(in crate::objects) async fn get_to_community( diff --git a/crates/apub/src/objects/user.rs b/crates/apub/src/objects/person.rs similarity index 82% rename from crates/apub/src/objects/user.rs rename to crates/apub/src/objects/person.rs index b6043d31d..87227dd14 100644 --- a/crates/apub/src/objects/user.rs +++ b/crates/apub/src/objects/person.rs @@ -22,7 +22,7 @@ use lemmy_api_structs::blocking; use lemmy_db_queries::{ApubObject, DbPool}; use lemmy_db_schema::{ naive_now, - source::user::{UserForm, User_}, + source::person::{Person as DbPerson, PersonForm}, }; use lemmy_utils::{ location_info, @@ -34,7 +34,7 @@ use lemmy_websocket::LemmyContext; use url::Url; #[async_trait::async_trait(?Send)] -impl ToApub for User_ { +impl ToApub for DbPerson { type ApubType = PersonExt; async fn to_apub(&self, _pool: &DbPool) -> Result { @@ -85,7 +85,7 @@ impl ToApub for User_ { } #[async_trait::async_trait(?Send)] -impl FromApub for User_ { +impl FromApub for DbPerson { type ApubType = PersonExt; async fn from_apub( @@ -94,17 +94,17 @@ impl FromApub for User_ { expected_domain: Url, request_counter: &mut i32, mod_action_allowed: bool, - ) -> Result { - let user_id = person.id_unchecked().context(location_info!())?.to_owned(); - let domain = user_id.domain().context(location_info!())?; + ) -> Result { + let person_id = person.id_unchecked().context(location_info!())?.to_owned(); + let domain = person_id.domain().context(location_info!())?; if domain == Settings::get().hostname() { - let user = blocking(context.pool(), move |conn| { - User_::read_from_apub_id(conn, &user_id.into()) + let person = blocking(context.pool(), move |conn| { + DbPerson::read_from_apub_id(conn, &person_id.into()) }) .await??; - Ok(user) + Ok(person) } else { - let user_form = UserForm::from_apub( + let person_form = PersonForm::from_apub( person, context, expected_domain, @@ -112,14 +112,17 @@ impl FromApub for User_ { mod_action_allowed, ) .await?; - let user = blocking(context.pool(), move |conn| User_::upsert(conn, &user_form)).await??; - Ok(user) + let person = blocking(context.pool(), move |conn| { + DbPerson::upsert(conn, &person_form) + }) + .await??; + Ok(person) } } } #[async_trait::async_trait(?Send)] -impl FromApubToForm for UserForm { +impl FromApubToForm for PersonForm { async fn from_apub( person: &PersonExt, _context: &LemmyContext, @@ -175,30 +178,20 @@ impl FromApubToForm for UserForm { check_slurs_opt(&preferred_username)?; check_slurs_opt(&bio)?; - Ok(UserForm { + Ok(PersonForm { name, preferred_username: Some(preferred_username), - password_encrypted: "".to_string(), - admin: false, banned: None, - email: None, + deleted: None, avatar: avatar.map(|o| o.map(|i| i.into())), banner: banner.map(|o| o.map(|i| i.into())), published: person.inner.published().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)?), bio: Some(bio), - local: false, + local: Some(false), 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()), inbox_url: Some(person.inner.inbox()?.to_owned().into()), shared_inbox_url: Some(shared_inbox), diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 14b43c6cb..1e1326385 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -1,7 +1,7 @@ use crate::{ check_is_apub_id_valid, extensions::{context::lemmy_context, page_extension::PageExtension}, - fetcher::user::get_or_fetch_and_upsert_user, + fetcher::person::get_or_fetch_and_upsert_person, objects::{ check_object_domain, check_object_for_community_or_site_ban, @@ -29,8 +29,8 @@ use lemmy_db_schema::{ self, source::{ community::Community, + person::Person, post::{Post, PostForm}, - user::User_, }, }; use lemmy_utils::{ @@ -51,7 +51,7 @@ impl ToApub for Post { let mut page = ApObject::new(Page::new()); 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 = blocking(pool, move |conn| Community::read(conn, community_id)).await??; @@ -159,7 +159,8 @@ impl FromApubToForm for PostForm { .as_single_xsd_any_uri() .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?; diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index ea9ae3f64..6eec9fa8c 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -1,7 +1,7 @@ use crate::{ check_is_apub_id_valid, extensions::context::lemmy_context, - fetcher::user::get_or_fetch_and_upsert_user, + fetcher::person::get_or_fetch_and_upsert_person, objects::{ check_object_domain, create_tombstone, @@ -22,8 +22,8 @@ use anyhow::Context; use lemmy_api_structs::blocking; use lemmy_db_queries::{Crud, DbPool}; use lemmy_db_schema::source::{ + person::Person, private_message::{PrivateMessage, PrivateMessageForm}, - user::User_, }; use lemmy_utils::{location_info, utils::convert_datetime, LemmyError}; use lemmy_websocket::LemmyContext; @@ -37,10 +37,10 @@ impl ToApub for PrivateMessage { let mut private_message = ApObject::new(Note::new()); 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 = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??; + let recipient = blocking(pool, move |conn| Person::read(conn, recipient_id)).await??; private_message .set_many_contexts(lemmy_context()?) @@ -106,7 +106,8 @@ impl FromApubToForm for PrivateMessageForm { .single_xsd_any_uri() .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 .to() .context(location_info!())? @@ -114,7 +115,7 @@ impl FromApubToForm for PrivateMessageForm { .single_xsd_any_uri() .context(location_info!())?; 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(); check_is_apub_id_valid(&Url::parse(&ap_id)?)?; diff --git a/crates/apub/src/routes.rs b/crates/apub/src/routes.rs index 2ec8c26d0..fecf333fa 100644 --- a/crates/apub/src/routes.rs +++ b/crates/apub/src/routes.rs @@ -9,10 +9,14 @@ use crate::{ get_apub_community_outbox, }, get_activity, + person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox}, 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, }; use actix_web::*; @@ -58,9 +62,12 @@ pub fn config(cfg: &mut web::ServiceConfig) { "/c/{community_name}/moderators", web::get().to(get_apub_community_moderators), ) - .route("/u/{user_name}", web::get().to(get_apub_user_http)) - .route("/u/{user_name}/outbox", web::get().to(get_apub_user_outbox)) - .route("/u/{user_name}/inbox", web::get().to(get_apub_user_inbox)) + .route("/u/{user_name}", web::get().to(get_apub_person_http)) + .route( + "/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("/comment/{comment_id}", web::get().to(get_apub_comment)) .route("/activities/{type_}/{id}", web::get().to(get_activity)), @@ -71,7 +78,7 @@ pub fn config(cfg: &mut web::ServiceConfig) { .wrap(digest_verifier) .guard(header_guard_content_type) .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)), ); } diff --git a/crates/db_queries/src/aggregates/comment_aggregates.rs b/crates/db_queries/src/aggregates/comment_aggregates.rs index 0826ae0d4..c55fef0ca 100644 --- a/crates/db_queries/src/aggregates/comment_aggregates.rs +++ b/crates/db_queries/src/aggregates/comment_aggregates.rs @@ -1,12 +1,12 @@ use diesel::{result::Error, *}; -use lemmy_db_schema::schema::comment_aggregates; +use lemmy_db_schema::{schema::comment_aggregates, CommentId}; use serde::Serialize; #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] #[table_name = "comment_aggregates"] pub struct CommentAggregates { pub id: i32, - pub comment_id: i32, + pub comment_id: CommentId, pub score: i64, pub upvotes: i64, pub downvotes: i64, @@ -14,7 +14,7 @@ pub struct CommentAggregates { } impl CommentAggregates { - pub fn read(conn: &PgConnection, comment_id: i32) -> Result { + pub fn read(conn: &PgConnection, comment_id: CommentId) -> Result { comment_aggregates::table .filter(comment_aggregates::comment_id.eq(comment_id)) .first::(conn) @@ -28,14 +28,12 @@ mod tests { establish_unpooled_connection, Crud, Likeable, - ListingType, - SortType, }; use lemmy_db_schema::source::{ comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::{Post, PostForm}, - user::{UserForm, User_}, }; use serial_test::serial; @@ -44,28 +42,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy_comment_agg".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -73,30 +61,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -104,11 +82,11 @@ mod tests { 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 { name: "TIL_comment_agg".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -134,7 +112,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -155,7 +133,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -171,7 +149,7 @@ mod tests { let child_comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -188,7 +166,7 @@ mod tests { let comment_like = CommentLikeForm { comment_id: inserted_comment.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -200,11 +178,11 @@ mod tests { assert_eq!(1, comment_aggs_before_delete.upvotes); 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 { comment_id: inserted_comment.id, post_id: inserted_post.id, - user_id: another_inserted_user.id, + person_id: another_inserted_person.id, score: -1, }; @@ -217,7 +195,7 @@ mod tests { assert_eq!(1, comment_aggs_after_dislike.downvotes); // 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(); assert_eq!(-1, after_like_remove.score); assert_eq!(0, after_like_remove.upvotes); @@ -231,8 +209,8 @@ mod tests { assert!(after_delete.is_err()); // This should delete all the associated rows, and fire triggers - User_::delete(&conn, another_inserted_user.id).unwrap(); - let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); - assert_eq!(1, user_num_deleted); + Person::delete(&conn, another_inserted_person.id).unwrap(); + let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); + assert_eq!(1, person_num_deleted); } } diff --git a/crates/db_queries/src/aggregates/community_aggregates.rs b/crates/db_queries/src/aggregates/community_aggregates.rs index ee60da9b2..bbe751ae5 100644 --- a/crates/db_queries/src/aggregates/community_aggregates.rs +++ b/crates/db_queries/src/aggregates/community_aggregates.rs @@ -1,12 +1,12 @@ use diesel::{result::Error, *}; -use lemmy_db_schema::schema::community_aggregates; +use lemmy_db_schema::{schema::community_aggregates, CommunityId}; use serde::Serialize; #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] #[table_name = "community_aggregates"] pub struct CommunityAggregates { pub id: i32, - pub community_id: i32, + pub community_id: CommunityId, pub subscribers: i64, pub posts: i64, pub comments: i64, @@ -18,7 +18,7 @@ pub struct CommunityAggregates { } impl CommunityAggregates { - pub fn read(conn: &PgConnection, community_id: i32) -> Result { + pub fn read(conn: &PgConnection, community_id: CommunityId) -> Result { community_aggregates::table .filter(community_aggregates::community_id.eq(community_id)) .first::(conn) @@ -32,14 +32,12 @@ mod tests { establish_unpooled_connection, Crud, Followable, - ListingType, - SortType, }; use lemmy_db_schema::source::{ comment::{Comment, CommentForm}, community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm}, + person::{Person, PersonForm}, post::{Post, PostForm}, - user::{UserForm, User_}, }; use serial_test::serial; @@ -48,28 +46,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy_community_agg".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -77,30 +65,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -108,11 +86,11 @@ mod tests { 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 { name: "TIL_community_agg".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -136,7 +114,7 @@ mod tests { let another_community = CommunityForm { name: "TIL_community_agg_2".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -158,25 +136,25 @@ mod tests { 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, - user_id: inserted_user.id, + person_id: inserted_person.id, 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, - user_id: another_inserted_user.id, + person_id: another_inserted_person.id, pending: false, }; - CommunityFollower::follow(&conn, &second_user_follow).unwrap(); + CommunityFollower::follow(&conn, &second_person_follow).unwrap(); let another_community_follow = CommunityFollowerForm { community_id: another_inserted_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, pending: false, }; @@ -186,7 +164,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -207,7 +185,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -223,7 +201,7 @@ mod tests { let child_comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -252,12 +230,12 @@ mod tests { assert_eq!(0, another_community_aggs.comments); // 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(); assert_eq!(1, after_unfollow.subscribers); // 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(); 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.posts); - // Remove the 2nd user - User_::delete(&conn, another_inserted_user.id).unwrap(); - let after_user_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap(); - assert_eq!(1, after_user_delete.subscribers); + // Remove the 2nd person + Person::delete(&conn, another_inserted_person.id).unwrap(); + let after_person_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap(); + assert_eq!(1, after_person_delete.subscribers); // This should delete all the associated rows, and fire triggers - let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); - assert_eq!(1, user_num_deleted); + let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); + assert_eq!(1, person_num_deleted); // Should be none found, since the creator was deleted let after_delete = CommunityAggregates::read(&conn, inserted_community.id); diff --git a/crates/db_queries/src/aggregates/mod.rs b/crates/db_queries/src/aggregates/mod.rs index bdef6591d..ad20f8a66 100644 --- a/crates/db_queries/src/aggregates/mod.rs +++ b/crates/db_queries/src/aggregates/mod.rs @@ -1,5 +1,5 @@ pub mod comment_aggregates; pub mod community_aggregates; +pub mod person_aggregates; pub mod post_aggregates; pub mod site_aggregates; -pub mod user_aggregates; diff --git a/crates/db_queries/src/aggregates/user_aggregates.rs b/crates/db_queries/src/aggregates/person_aggregates.rs similarity index 65% rename from crates/db_queries/src/aggregates/user_aggregates.rs rename to crates/db_queries/src/aggregates/person_aggregates.rs index bdd16932a..c1082c4b6 100644 --- a/crates/db_queries/src/aggregates/user_aggregates.rs +++ b/crates/db_queries/src/aggregates/person_aggregates.rs @@ -1,22 +1,22 @@ use diesel::{result::Error, *}; -use lemmy_db_schema::schema::user_aggregates; +use lemmy_db_schema::{schema::person_aggregates, PersonId}; use serde::Serialize; #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] -#[table_name = "user_aggregates"] -pub struct UserAggregates { +#[table_name = "person_aggregates"] +pub struct PersonAggregates { pub id: i32, - pub user_id: i32, + pub person_id: PersonId, pub post_count: i64, pub post_score: i64, pub comment_count: i64, pub comment_score: i64, } -impl UserAggregates { - pub fn read(conn: &PgConnection, user_id: i32) -> Result { - user_aggregates::table - .filter(user_aggregates::user_id.eq(user_id)) +impl PersonAggregates { + pub fn read(conn: &PgConnection, person_id: PersonId) -> Result { + person_aggregates::table + .filter(person_aggregates::person_id.eq(person_id)) .first::(conn) } } @@ -24,18 +24,16 @@ impl UserAggregates { #[cfg(test)] mod tests { use crate::{ - aggregates::user_aggregates::UserAggregates, + aggregates::person_aggregates::PersonAggregates, establish_unpooled_connection, Crud, Likeable, - ListingType, - SortType, }; use lemmy_db_schema::source::{ comment::{Comment, CommentForm, CommentLike, CommentLikeForm}, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::{Post, PostForm, PostLike, PostLikeForm}, - user::{UserForm, User_}, }; use serial_test::serial; @@ -44,28 +42,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy_user_agg".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -73,30 +61,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -104,11 +82,11 @@ mod tests { 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 { name: "TIL_site_agg".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -134,7 +112,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -155,7 +133,7 @@ mod tests { let post_like = PostLikeForm { post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -163,7 +141,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -179,7 +157,7 @@ mod tests { let mut comment_like = CommentLikeForm { comment_id: inserted_comment.id, - user_id: inserted_user.id, + person_id: inserted_person.id, post_id: inserted_post.id, score: 1, }; @@ -188,7 +166,7 @@ mod tests { let mut child_comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -204,28 +182,29 @@ mod tests { let child_comment_like = CommentLikeForm { comment_id: inserted_child_comment.id, - user_id: another_inserted_user.id, + person_id: another_inserted_person.id, post_id: inserted_post.id, score: 1, }; 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, user_aggregates_before_delete.post_score); - assert_eq!(2, user_aggregates_before_delete.comment_count); - assert_eq!(2, user_aggregates_before_delete.comment_score); + assert_eq!(1, person_aggregates_before_delete.post_count); + assert_eq!(1, person_aggregates_before_delete.post_score); + assert_eq!(2, person_aggregates_before_delete.comment_count); + assert_eq!(2, person_aggregates_before_delete.comment_score); // Remove a post like - PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap(); - let after_post_like_remove = UserAggregates::read(&conn, inserted_user.id).unwrap(); + PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap(); + let after_post_like_remove = PersonAggregates::read(&conn, inserted_person.id).unwrap(); assert_eq!(0, after_post_like_remove.post_score); // Remove a parent comment (the scores should also be removed) 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_score); @@ -235,24 +214,24 @@ mod tests { Comment::create(&conn, &child_comment_form).unwrap(); comment_like.comment_id = new_parent_comment.id; 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!(1, after_comment_add.comment_score); 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_count); assert_eq!(0, after_post_delete.post_score); assert_eq!(0, after_post_delete.post_count); // This should delete all the associated rows, and fire triggers - let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); - assert_eq!(1, user_num_deleted); - User_::delete(&conn, another_inserted_user.id).unwrap(); + let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); + assert_eq!(1, person_num_deleted); + Person::delete(&conn, another_inserted_person.id).unwrap(); // 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()); } } diff --git a/crates/db_queries/src/aggregates/post_aggregates.rs b/crates/db_queries/src/aggregates/post_aggregates.rs index 404257a7b..aa5e774e0 100644 --- a/crates/db_queries/src/aggregates/post_aggregates.rs +++ b/crates/db_queries/src/aggregates/post_aggregates.rs @@ -1,12 +1,12 @@ use diesel::{result::Error, *}; -use lemmy_db_schema::schema::post_aggregates; +use lemmy_db_schema::{schema::post_aggregates, PostId}; use serde::Serialize; #[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)] #[table_name = "post_aggregates"] pub struct PostAggregates { pub id: i32, - pub post_id: i32, + pub post_id: PostId, pub comments: i64, pub score: i64, pub upvotes: i64, @@ -18,7 +18,7 @@ pub struct PostAggregates { } impl PostAggregates { - pub fn read(conn: &PgConnection, post_id: i32) -> Result { + pub fn read(conn: &PgConnection, post_id: PostId) -> Result { post_aggregates::table .filter(post_aggregates::post_id.eq(post_id)) .first::(conn) @@ -32,14 +32,12 @@ mod tests { establish_unpooled_connection, Crud, Likeable, - ListingType, - SortType, }; use lemmy_db_schema::source::{ comment::{Comment, CommentForm}, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::{Post, PostForm, PostLike, PostLikeForm}, - user::{UserForm, User_}, }; use serial_test::serial; @@ -48,28 +46,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy_community_agg".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -77,30 +65,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -108,11 +86,11 @@ mod tests { 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 { name: "TIL_community_agg".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -138,7 +116,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -159,7 +137,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -175,7 +153,7 @@ mod tests { let child_comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -191,7 +169,7 @@ mod tests { let post_like = PostLikeForm { post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -204,10 +182,10 @@ mod tests { assert_eq!(1, post_aggs_before_delete.upvotes); 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 { post_id: inserted_post.id, - user_id: another_inserted_user.id, + person_id: another_inserted_person.id, score: -1, }; @@ -229,7 +207,7 @@ mod tests { assert_eq!(1, after_comment_delete.downvotes); // 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(); assert_eq!(0, after_like_remove.comments); assert_eq!(-1, after_like_remove.score); @@ -237,9 +215,9 @@ mod tests { assert_eq!(1, after_like_remove.downvotes); // This should delete all the associated rows, and fire triggers - User_::delete(&conn, another_inserted_user.id).unwrap(); - let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); - assert_eq!(1, user_num_deleted); + Person::delete(&conn, another_inserted_person.id).unwrap(); + let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); + assert_eq!(1, person_num_deleted); // Should be none found, since the creator was deleted let after_delete = PostAggregates::read(&conn, inserted_post.id); diff --git a/crates/db_queries/src/aggregates/site_aggregates.rs b/crates/db_queries/src/aggregates/site_aggregates.rs index 81afed5c4..a685ad0da 100644 --- a/crates/db_queries/src/aggregates/site_aggregates.rs +++ b/crates/db_queries/src/aggregates/site_aggregates.rs @@ -25,19 +25,13 @@ impl SiteAggregates { #[cfg(test)] mod tests { - use crate::{ - aggregates::site_aggregates::SiteAggregates, - establish_unpooled_connection, - Crud, - ListingType, - SortType, - }; + use crate::{aggregates::site_aggregates::SiteAggregates, establish_unpooled_connection, Crud}; use lemmy_db_schema::source::{ comment::{Comment, CommentForm}, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::{Post, PostForm}, site::{Site, SiteForm}, - user::{UserForm, User_}, }; use serial_test::serial; @@ -46,28 +40,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy_site_agg".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -75,14 +59,14 @@ mod tests { 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 { name: "test_site".into(), description: None, icon: None, banner: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, enable_downvotes: true, open_registration: true, enable_nsfw: true, @@ -93,7 +77,7 @@ mod tests { let new_community = CommunityForm { name: "TIL_site_agg".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -119,7 +103,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -142,7 +126,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -159,7 +143,7 @@ mod tests { let child_comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -187,8 +171,8 @@ mod tests { assert_eq!(0, site_aggregates_after_post_delete.comments); // This shouuld delete all the associated rows, and fire triggers - let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap(); - assert_eq!(1, user_num_deleted); + let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap(); + assert_eq!(1, person_num_deleted); let after_delete = SiteAggregates::read(&conn); assert!(after_delete.is_err()); diff --git a/crates/db_queries/src/lib.rs b/crates/db_queries/src/lib.rs index f19d36263..285ba3323 100644 --- a/crates/db_queries/src/lib.rs +++ b/crates/db_queries/src/lib.rs @@ -13,7 +13,7 @@ extern crate diesel_migrations; extern crate serial_test; use diesel::{result::Error, *}; -use lemmy_db_schema::DbUrl; +use lemmy_db_schema::{CommunityId, DbUrl, PersonId}; use lemmy_utils::ApiError; use regex::Regex; use serde::{Deserialize, Serialize}; @@ -25,17 +25,17 @@ pub mod source; pub type DbPool = diesel::r2d2::Pool>; -pub trait Crud { - fn create(conn: &PgConnection, form: &T) -> Result +pub trait Crud { + fn create(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn read(conn: &PgConnection, id: i32) -> Result + fn read(conn: &PgConnection, id: IdType) -> Result where Self: Sized; - fn update(conn: &PgConnection, id: i32, form: &T) -> Result + fn update(conn: &PgConnection, id: IdType, form: &Form) -> Result where Self: Sized; - fn delete(_conn: &PgConnection, _id: i32) -> Result + fn delete(_conn: &PgConnection, _id: IdType) -> Result where Self: Sized, { @@ -43,81 +43,85 @@ pub trait Crud { } } -pub trait Followable { - fn follow(conn: &PgConnection, form: &T) -> Result +pub trait Followable
{ + fn follow(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn follow_accepted(conn: &PgConnection, community_id: i32, user_id: i32) -> Result + fn follow_accepted( + conn: &PgConnection, + community_id: CommunityId, + person_id: PersonId, + ) -> Result where Self: Sized; - fn unfollow(conn: &PgConnection, form: &T) -> Result + fn unfollow(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn has_local_followers(conn: &PgConnection, community_id: i32) -> Result; + fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result; } -pub trait Joinable { - fn join(conn: &PgConnection, form: &T) -> Result +pub trait Joinable { + fn join(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn leave(conn: &PgConnection, form: &T) -> Result + fn leave(conn: &PgConnection, form: &Form) -> Result where Self: Sized; } -pub trait Likeable { - fn like(conn: &PgConnection, form: &T) -> Result +pub trait Likeable { + fn like(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn remove(conn: &PgConnection, user_id: i32, item_id: i32) -> Result + fn remove(conn: &PgConnection, person_id: PersonId, item_id: IdType) -> Result where Self: Sized; } -pub trait Bannable { - fn ban(conn: &PgConnection, form: &T) -> Result +pub trait Bannable { + fn ban(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn unban(conn: &PgConnection, form: &T) -> Result + fn unban(conn: &PgConnection, form: &Form) -> Result where Self: Sized; } -pub trait Saveable { - fn save(conn: &PgConnection, form: &T) -> Result +pub trait Saveable { + fn save(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn unsave(conn: &PgConnection, form: &T) -> Result + fn unsave(conn: &PgConnection, form: &Form) -> Result where Self: Sized; } -pub trait Readable { - fn mark_as_read(conn: &PgConnection, form: &T) -> Result +pub trait Readable { + fn mark_as_read(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn mark_as_unread(conn: &PgConnection, form: &T) -> Result + fn mark_as_unread(conn: &PgConnection, form: &Form) -> Result where Self: Sized; } -pub trait Reportable { - fn report(conn: &PgConnection, form: &T) -> Result +pub trait Reportable { + fn report(conn: &PgConnection, form: &Form) -> Result where Self: Sized; - fn resolve(conn: &PgConnection, report_id: i32, resolver_id: i32) -> Result + fn resolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result where Self: Sized; - fn unresolve(conn: &PgConnection, report_id: i32, resolver_id: i32) -> Result + fn unresolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result where Self: Sized; } -pub trait ApubObject { +pub trait ApubObject { fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result where Self: Sized; - fn upsert(conn: &PgConnection, user_form: &T) -> Result + fn upsert(conn: &PgConnection, user_form: &Form) -> Result where Self: Sized; } diff --git a/crates/db_queries/src/source/activity.rs b/crates/db_queries/src/source/activity.rs index 56b904e89..1ec9b8d16 100644 --- a/crates/db_queries/src/source/activity.rs +++ b/crates/db_queries/src/source/activity.rs @@ -9,7 +9,7 @@ use std::{ io::{Error as IoError, ErrorKind}, }; -impl Crud for Activity { +impl Crud for Activity { fn read(conn: &PgConnection, activity_id: i32) -> Result { use lemmy_db_schema::schema::activity::dsl::*; activity.find(activity_id).first::(conn) @@ -122,16 +122,10 @@ impl Activity_ for Activity { #[cfg(test)] mod tests { use super::*; - use crate::{ - establish_unpooled_connection, - source::activity::Activity_, - Crud, - ListingType, - SortType, - }; + use crate::{establish_unpooled_connection, source::activity::Activity_}; use lemmy_db_schema::source::{ activity::{Activity, ActivityForm}, - user::{UserForm, User_}, + person::{Person, PersonForm}, }; use serde_json::Value; use serial_test::serial; @@ -142,28 +136,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let creator_form = UserForm { + let creator_form = PersonForm { name: "activity_creator_pm".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -171,7 +155,7 @@ mod tests { 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: DbUrl = Url::parse( "https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c", @@ -214,7 +198,7 @@ mod tests { 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(); - User_::delete(&conn, inserted_creator.id).unwrap(); + Person::delete(&conn, inserted_creator.id).unwrap(); Activity::delete(&conn, inserted_activity.id).unwrap(); assert_eq!(expected_activity, read_activity); diff --git a/crates/db_queries/src/source/comment.rs b/crates/db_queries/src/source/comment.rs index 8dc9050cb..69ac4c081 100644 --- a/crates/db_queries/src/source/comment.rs +++ b/crates/db_queries/src/source/comment.rs @@ -10,40 +10,54 @@ use lemmy_db_schema::{ CommentSaved, CommentSavedForm, }, + CommentId, DbUrl, + PersonId, }; pub trait Comment_ { - fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: DbUrl) -> Result; + fn update_ap_id( + conn: &PgConnection, + comment_id: CommentId, + apub_id: DbUrl, + ) -> Result; fn permadelete_for_creator( conn: &PgConnection, - for_creator_id: i32, + for_creator_id: PersonId, ) -> Result, Error>; fn update_deleted( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_deleted: bool, ) -> Result; fn update_removed( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_removed: bool, ) -> Result; fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, + for_creator_id: PersonId, new_removed: bool, ) -> Result, Error>; - fn update_read(conn: &PgConnection, comment_id: i32, new_read: bool) -> Result; + fn update_read( + conn: &PgConnection, + comment_id: CommentId, + new_read: bool, + ) -> Result; fn update_content( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_content: &str, ) -> Result; } impl Comment_ for Comment { - fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: DbUrl) -> Result { + fn update_ap_id( + conn: &PgConnection, + comment_id: CommentId, + apub_id: DbUrl, + ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; diesel::update(comment.find(comment_id)) @@ -51,7 +65,10 @@ impl Comment_ for Comment { .get_result::(conn) } - fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result, Error> { + fn permadelete_for_creator( + conn: &PgConnection, + for_creator_id: PersonId, + ) -> Result, Error> { use lemmy_db_schema::schema::comment::dsl::*; diesel::update(comment.filter(creator_id.eq(for_creator_id))) .set(( @@ -64,7 +81,7 @@ impl Comment_ for Comment { fn update_deleted( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_deleted: bool, ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; @@ -75,7 +92,7 @@ impl Comment_ for Comment { fn update_removed( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_removed: bool, ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; @@ -86,7 +103,7 @@ impl Comment_ for Comment { fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, + for_creator_id: PersonId, new_removed: bool, ) -> Result, Error> { use lemmy_db_schema::schema::comment::dsl::*; @@ -95,7 +112,11 @@ impl Comment_ for Comment { .get_results::(conn) } - fn update_read(conn: &PgConnection, comment_id: i32, new_read: bool) -> Result { + fn update_read( + conn: &PgConnection, + comment_id: CommentId, + new_read: bool, + ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; diesel::update(comment.find(comment_id)) .set(read.eq(new_read)) @@ -104,7 +125,7 @@ impl Comment_ for Comment { fn update_content( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, new_content: &str, ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; @@ -114,13 +135,13 @@ impl Comment_ for Comment { } } -impl Crud for Comment { - fn read(conn: &PgConnection, comment_id: i32) -> Result { +impl Crud for Comment { + fn read(conn: &PgConnection, comment_id: CommentId) -> Result { use lemmy_db_schema::schema::comment::dsl::*; comment.find(comment_id).first::(conn) } - fn delete(conn: &PgConnection, comment_id: i32) -> Result { + fn delete(conn: &PgConnection, comment_id: CommentId) -> Result { use lemmy_db_schema::schema::comment::dsl::*; diesel::delete(comment.find(comment_id)).execute(conn) } @@ -134,7 +155,7 @@ impl Crud for Comment { fn update( conn: &PgConnection, - comment_id: i32, + comment_id: CommentId, comment_form: &CommentForm, ) -> Result { use lemmy_db_schema::schema::comment::dsl::*; @@ -161,22 +182,26 @@ impl ApubObject for Comment { } } -impl Likeable for CommentLike { +impl Likeable for CommentLike { fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result { use lemmy_db_schema::schema::comment_like::dsl::*; insert_into(comment_like) .values(comment_like_form) - .on_conflict((comment_id, user_id)) + .on_conflict((comment_id, person_id)) .do_update() .set(comment_like_form) .get_result::(conn) } - fn remove(conn: &PgConnection, user_id: i32, comment_id: i32) -> Result { + fn remove( + conn: &PgConnection, + person_id: PersonId, + comment_id: CommentId, + ) -> Result { use lemmy_db_schema::schema::comment_like::dsl; diesel::delete( dsl::comment_like .filter(dsl::comment_id.eq(comment_id)) - .filter(dsl::user_id.eq(user_id)), + .filter(dsl::person_id.eq(person_id)), ) .execute(conn) } @@ -187,7 +212,7 @@ impl Saveable for CommentSaved { use lemmy_db_schema::schema::comment_saved::dsl::*; insert_into(comment_saved) .values(comment_saved_form) - .on_conflict((comment_id, user_id)) + .on_conflict((comment_id, person_id)) .do_update() .set(comment_saved_form) .get_result::(conn) @@ -197,7 +222,7 @@ impl Saveable for CommentSaved { diesel::delete( comment_saved .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) } @@ -205,12 +230,12 @@ impl Saveable for CommentSaved { #[cfg(test)] 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::{ comment::*, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::*, - user::{UserForm, User_}, }; use serial_test::serial; @@ -219,28 +244,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "terry".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -248,13 +263,13 @@ mod tests { 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 { name: "test community".to_string(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -276,7 +291,7 @@ mod tests { let new_post = PostForm { name: "A test post".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, url: None, body: None, community_id: inserted_community.id, @@ -299,7 +314,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -316,7 +331,7 @@ mod tests { let expected_comment = Comment { id: inserted_comment.id, content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: false, deleted: false, @@ -330,7 +345,7 @@ mod tests { let child_comment_form = CommentForm { content: "A child comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, parent_id: Some(inserted_comment.id), removed: None, @@ -348,7 +363,7 @@ mod tests { let comment_like_form = CommentLikeForm { comment_id: inserted_comment.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -358,7 +373,7 @@ mod tests { id: inserted_comment_like.id, comment_id: inserted_comment.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_comment_like.published, score: 1, }; @@ -366,7 +381,7 @@ mod tests { // Comment Saved let comment_saved_form = CommentSavedForm { 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(); @@ -374,19 +389,19 @@ mod tests { let expected_comment_saved = CommentSaved { id: inserted_comment_saved.id, comment_id: inserted_comment.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_comment_saved.published, }; let read_comment = Comment::read(&conn, inserted_comment.id).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 num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap(); Comment::delete(&conn, inserted_child_comment.id).unwrap(); Post::delete(&conn, inserted_post.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, inserted_comment); diff --git a/crates/db_queries/src/source/comment_report.rs b/crates/db_queries/src/source/comment_report.rs index bf42704ea..87b936062 100644 --- a/crates/db_queries/src/source/comment_report.rs +++ b/crates/db_queries/src/source/comment_report.rs @@ -3,6 +3,7 @@ use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::{ naive_now, source::comment_report::{CommentReport, CommentReportForm}, + PersonId, }; impl Reportable for CommentReport { @@ -22,7 +23,11 @@ impl Reportable for CommentReport { /// * `conn` - the postgres connection /// * `report_id` - the id of the report to resolve /// * `by_resolver_id` - the id of the user resolving the report - fn resolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result { + fn resolve( + conn: &PgConnection, + report_id: i32, + by_resolver_id: PersonId, + ) -> Result { use lemmy_db_schema::schema::comment_report::dsl::*; update(comment_report.find(report_id)) .set(( @@ -38,7 +43,11 @@ impl Reportable for CommentReport { /// * `conn` - the postgres connection /// * `report_id` - the id of the report to unresolve /// * `by_resolver_id` - the id of the user unresolving the report - fn unresolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result { + fn unresolve( + conn: &PgConnection, + report_id: i32, + by_resolver_id: PersonId, + ) -> Result { use lemmy_db_schema::schema::comment_report::dsl::*; update(comment_report.find(report_id)) .set(( diff --git a/crates/db_queries/src/source/community.rs b/crates/db_queries/src/source/community.rs index 03484816c..5b7fc92c8 100644 --- a/crates/db_queries/src/source/community.rs +++ b/crates/db_queries/src/source/community.rs @@ -9,10 +9,12 @@ use lemmy_db_schema::{ CommunityForm, CommunityModerator, CommunityModeratorForm, - CommunityUserBan, - CommunityUserBanForm, + CommunityPersonBan, + CommunityPersonBanForm, }, + CommunityId, DbUrl, + PersonId, }; mod safe_type { @@ -59,13 +61,13 @@ mod safe_type { } } -impl Crud for Community { - fn read(conn: &PgConnection, community_id: i32) -> Result { +impl Crud for Community { + fn read(conn: &PgConnection, community_id: CommunityId) -> Result { use lemmy_db_schema::schema::community::dsl::*; community.find(community_id).first::(conn) } - fn delete(conn: &PgConnection, community_id: i32) -> Result { + fn delete(conn: &PgConnection, community_id: CommunityId) -> Result { use lemmy_db_schema::schema::community::dsl::*; diesel::delete(community.find(community_id)).execute(conn) } @@ -79,7 +81,7 @@ impl Crud for Community { fn update( conn: &PgConnection, - community_id: i32, + community_id: CommunityId, new_community: &CommunityForm, ) -> Result { use lemmy_db_schema::schema::community::dsl::*; @@ -112,23 +114,23 @@ pub trait Community_ { fn read_from_name(conn: &PgConnection, community_name: &str) -> Result; fn update_deleted( conn: &PgConnection, - community_id: i32, + community_id: CommunityId, new_deleted: bool, ) -> Result; fn update_removed( conn: &PgConnection, - community_id: i32, + community_id: CommunityId, new_removed: bool, ) -> Result; fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, + for_creator_id: PersonId, new_removed: bool, ) -> Result, Error>; fn update_creator( conn: &PgConnection, - community_id: i32, - new_creator_id: i32, + community_id: CommunityId, + new_creator_id: PersonId, ) -> Result; fn distinct_federated_communities(conn: &PgConnection) -> Result, Error>; fn read_from_followers_url( @@ -148,7 +150,7 @@ impl Community_ for Community { fn update_deleted( conn: &PgConnection, - community_id: i32, + community_id: CommunityId, new_deleted: bool, ) -> Result { use lemmy_db_schema::schema::community::dsl::*; @@ -159,7 +161,7 @@ impl Community_ for Community { fn update_removed( conn: &PgConnection, - community_id: i32, + community_id: CommunityId, new_removed: bool, ) -> Result { use lemmy_db_schema::schema::community::dsl::*; @@ -170,7 +172,7 @@ impl Community_ for Community { fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, + for_creator_id: PersonId, new_removed: bool, ) -> Result, Error> { use lemmy_db_schema::schema::community::dsl::*; @@ -181,8 +183,8 @@ impl Community_ for Community { fn update_creator( conn: &PgConnection, - community_id: i32, - new_creator_id: i32, + community_id: CommunityId, + new_creator_id: PersonId, ) -> Result { use lemmy_db_schema::schema::community::dsl::*; diesel::update(community.find(community_id)) @@ -209,74 +211,80 @@ impl Community_ for Community { impl Joinable for CommunityModerator { fn join( conn: &PgConnection, - community_user_form: &CommunityModeratorForm, + community_moderator_form: &CommunityModeratorForm, ) -> Result { use lemmy_db_schema::schema::community_moderator::dsl::*; insert_into(community_moderator) - .values(community_user_form) + .values(community_moderator_form) .get_result::(conn) } fn leave( conn: &PgConnection, - community_user_form: &CommunityModeratorForm, + community_moderator_form: &CommunityModeratorForm, ) -> Result { use lemmy_db_schema::schema::community_moderator::dsl::*; diesel::delete( community_moderator - .filter(community_id.eq(community_user_form.community_id)) - .filter(user_id.eq(community_user_form.user_id)), + .filter(community_id.eq(community_moderator_form.community_id)) + .filter(person_id.eq(community_moderator_form.person_id)), ) .execute(conn) } } pub trait CommunityModerator_ { - fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result; - fn get_user_moderated_communities( + fn delete_for_community( conn: &PgConnection, - for_user_id: i32, - ) -> Result, Error>; + for_community_id: CommunityId, + ) -> Result; + fn get_person_moderated_communities( + conn: &PgConnection, + for_person_id: PersonId, + ) -> Result, Error>; } impl CommunityModerator_ for CommunityModerator { - fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result { + fn delete_for_community( + conn: &PgConnection, + for_community_id: CommunityId, + ) -> Result { use lemmy_db_schema::schema::community_moderator::dsl::*; 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, - for_user_id: i32, - ) -> Result, Error> { + for_person_id: PersonId, + ) -> Result, Error> { use lemmy_db_schema::schema::community_moderator::dsl::*; community_moderator - .filter(user_id.eq(for_user_id)) + .filter(person_id.eq(for_person_id)) .select(community_id) - .load::(conn) + .load::(conn) } } -impl Bannable for CommunityUserBan { +impl Bannable for CommunityPersonBan { fn ban( conn: &PgConnection, - community_user_ban_form: &CommunityUserBanForm, + community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use lemmy_db_schema::schema::community_user_ban::dsl::*; - insert_into(community_user_ban) - .values(community_user_ban_form) + use lemmy_db_schema::schema::community_person_ban::dsl::*; + insert_into(community_person_ban) + .values(community_person_ban_form) .get_result::(conn) } fn unban( conn: &PgConnection, - community_user_ban_form: &CommunityUserBanForm, + community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use lemmy_db_schema::schema::community_user_ban::dsl::*; + use lemmy_db_schema::schema::community_person_ban::dsl::*; diesel::delete( - community_user_ban - .filter(community_id.eq(community_user_ban_form.community_id)) - .filter(user_id.eq(community_user_ban_form.user_id)), + community_person_ban + .filter(community_id.eq(community_person_ban_form.community_id)) + .filter(person_id.eq(community_person_ban_form.person_id)), ) .execute(conn) } @@ -290,12 +298,16 @@ impl Followable for CommunityFollower { use lemmy_db_schema::schema::community_follower::dsl::*; insert_into(community_follower) .values(community_follower_form) - .on_conflict((community_id, user_id)) + .on_conflict((community_id, person_id)) .do_update() .set(community_follower_form) .get_result::(conn) } - fn follow_accepted(conn: &PgConnection, community_id_: i32, user_id_: i32) -> Result + fn follow_accepted( + conn: &PgConnection, + community_id_: CommunityId, + person_id_: PersonId, + ) -> Result where Self: Sized, { @@ -303,7 +315,7 @@ impl Followable for CommunityFollower { diesel::update( community_follower .filter(community_id.eq(community_id_)) - .filter(user_id.eq(user_id_)), + .filter(person_id.eq(person_id_)), ) .set(pending.eq(true)) .get_result::(conn) @@ -316,13 +328,13 @@ impl Followable for CommunityFollower { diesel::delete( community_follower .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) } // 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 - fn has_local_followers(conn: &PgConnection, community_id_: i32) -> Result { + fn has_local_followers(conn: &PgConnection, community_id_: CommunityId) -> Result { use lemmy_db_schema::schema::community_follower::dsl::*; diesel::select(exists( community_follower.filter(community_id.eq(community_id_)), @@ -333,16 +345,8 @@ impl Followable for CommunityFollower { #[cfg(test)] mod tests { - use crate::{ - establish_unpooled_connection, - Bannable, - Crud, - Followable, - Joinable, - ListingType, - SortType, - }; - use lemmy_db_schema::source::{community::*, user::*}; + use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable}; + use lemmy_db_schema::source::{community::*, person::*}; use serial_test::serial; #[test] @@ -350,28 +354,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "bobbee".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -379,11 +373,11 @@ mod tests { 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 { name: "TIL".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, title: "nada".to_owned(), description: None, nsfw: false, @@ -407,7 +401,7 @@ mod tests { let expected_community = Community { id: inserted_community.id, - creator_id: inserted_user.id, + creator_id: inserted_person.id, name: "TIL".into(), title: "nada".to_owned(), description: None, @@ -430,7 +424,7 @@ mod tests { let community_follower_form = CommunityFollowerForm { community_id: inserted_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, pending: false, }; @@ -440,55 +434,56 @@ mod tests { let expected_community_follower = CommunityFollower { id: inserted_community_follower.id, community_id: inserted_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, pending: Some(false), published: inserted_community_follower.published, }; - let community_user_form = CommunityModeratorForm { + let community_moderator_form = CommunityModeratorForm { 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 { - id: inserted_community_user.id, + let expected_community_moderator = CommunityModerator { + id: inserted_community_moderator.id, community_id: inserted_community.id, - user_id: inserted_user.id, - published: inserted_community_user.published, + person_id: inserted_person.id, + published: inserted_community_moderator.published, }; - let community_user_ban_form = CommunityUserBanForm { + let community_person_ban_form = CommunityPersonBanForm { community_id: inserted_community.id, - user_id: inserted_user.id, + person_id: inserted_person.id, }; - let inserted_community_user_ban = - CommunityUserBan::ban(&conn, &community_user_ban_form).unwrap(); + let inserted_community_person_ban = + CommunityPersonBan::ban(&conn, &community_person_ban_form).unwrap(); - let expected_community_user_ban = CommunityUserBan { - id: inserted_community_user_ban.id, + let expected_community_person_ban = CommunityPersonBan { + id: inserted_community_person_ban.id, community_id: inserted_community.id, - user_id: inserted_user.id, - published: inserted_community_user_ban.published, + person_id: inserted_person.id, + published: inserted_community_person_ban.published, }; let read_community = Community::read(&conn, inserted_community.id).unwrap(); let updated_community = Community::update(&conn, inserted_community.id, &new_community).unwrap(); let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap(); - let left_community = CommunityModerator::leave(&conn, &community_user_form).unwrap(); - let unban = CommunityUserBan::unban(&conn, &community_user_ban_form).unwrap(); + let left_community = CommunityModerator::leave(&conn, &community_moderator_form).unwrap(); + let unban = CommunityPersonBan::unban(&conn, &community_person_ban_form).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, inserted_community); assert_eq!(expected_community, updated_community); assert_eq!(expected_community_follower, inserted_community_follower); - assert_eq!(expected_community_user, inserted_community_user); - assert_eq!(expected_community_user_ban, inserted_community_user_ban); + assert_eq!(expected_community_moderator, inserted_community_moderator); + assert_eq!(expected_community_person_ban, inserted_community_person_ban); assert_eq!(1, ignored_community); assert_eq!(1, left_community); assert_eq!(1, unban); diff --git a/crates/db_queries/src/source/local_user.rs b/crates/db_queries/src/source/local_user.rs new file mode 100644 index 000000000..cd93d3fb1 --- /dev/null +++ b/crates/db_queries/src/source/local_user.rs @@ -0,0 +1,127 @@ +use crate::Crud; +use bcrypt::{hash, DEFAULT_COST}; +use diesel::{dsl::*, result::Error, *}; +use lemmy_db_schema::{ + schema::local_user::dsl::*, + source::local_user::{LocalUser, LocalUserForm}, + LocalUserId, + PersonId, +}; + +mod safe_type { + use crate::ToSafe; + use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser}; + + type Columns = (id, person_id, admin, matrix_user_id); + + impl ToSafe for LocalUser { + type SafeColumns = Columns; + fn safe_columns_tuple() -> Self::SafeColumns { + (id, person_id, admin, matrix_user_id) + } + } +} + +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, + ); + + 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, + ) + } + } +} + +pub trait LocalUser_ { + fn register(conn: &PgConnection, form: &LocalUserForm) -> Result; + fn update_password( + conn: &PgConnection, + local_user_id: LocalUserId, + new_password: &str, + ) -> Result; + fn add_admin(conn: &PgConnection, person_id: PersonId, added: bool) -> Result; +} + +impl LocalUser_ for LocalUser { + fn register(conn: &PgConnection, form: &LocalUserForm) -> Result { + 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 { + 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),)) + .get_result::(conn) + } + + fn add_admin(conn: &PgConnection, for_person_id: PersonId, added: bool) -> Result { + diesel::update(local_user.filter(person_id.eq(for_person_id))) + .set(admin.eq(added)) + .get_result::(conn) + } +} + +impl Crud for LocalUser { + fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result { + local_user.find(local_user_id).first::(conn) + } + fn delete(conn: &PgConnection, local_user_id: LocalUserId) -> Result { + diesel::delete(local_user.find(local_user_id)).execute(conn) + } + fn create(conn: &PgConnection, form: &LocalUserForm) -> Result { + insert_into(local_user) + .values(form) + .get_result::(conn) + } + fn update( + conn: &PgConnection, + local_user_id: LocalUserId, + form: &LocalUserForm, + ) -> Result { + diesel::update(local_user.find(local_user_id)) + .set(form) + .get_result::(conn) + } +} diff --git a/crates/db_queries/src/source/mod.rs b/crates/db_queries/src/source/mod.rs index a39dc1108..db928bd4f 100644 --- a/crates/db_queries/src/source/mod.rs +++ b/crates/db_queries/src/source/mod.rs @@ -2,11 +2,12 @@ pub mod activity; pub mod comment; pub mod comment_report; pub mod community; +pub mod local_user; pub mod moderator; pub mod password_reset_request; +pub mod person; +pub mod person_mention; pub mod post; pub mod post_report; pub mod private_message; pub mod site; -pub mod user; -pub mod user_mention; diff --git a/crates/db_queries/src/source/moderator.rs b/crates/db_queries/src/source/moderator.rs index 469ada089..526fc2bd8 100644 --- a/crates/db_queries/src/source/moderator.rs +++ b/crates/db_queries/src/source/moderator.rs @@ -2,7 +2,7 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; use lemmy_db_schema::source::moderator::*; -impl Crud for ModRemovePost { +impl Crud for ModRemovePost { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_post::dsl::*; mod_remove_post.find(from_id).first::(conn) @@ -23,7 +23,7 @@ impl Crud for ModRemovePost { } } -impl Crud for ModLockPost { +impl Crud for ModLockPost { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_lock_post::dsl::*; mod_lock_post.find(from_id).first::(conn) @@ -44,7 +44,7 @@ impl Crud for ModLockPost { } } -impl Crud for ModStickyPost { +impl Crud for ModStickyPost { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_sticky_post::dsl::*; mod_sticky_post.find(from_id).first::(conn) @@ -65,7 +65,7 @@ impl Crud for ModStickyPost { } } -impl Crud for ModRemoveComment { +impl Crud for ModRemoveComment { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_comment::dsl::*; mod_remove_comment.find(from_id).first::(conn) @@ -86,7 +86,7 @@ impl Crud for ModRemoveComment { } } -impl Crud for ModRemoveCommunity { +impl Crud for ModRemoveCommunity { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_remove_community::dsl::*; mod_remove_community.find(from_id).first::(conn) @@ -111,7 +111,7 @@ impl Crud for ModRemoveCommunity { } } -impl Crud for ModBanFromCommunity { +impl Crud for ModBanFromCommunity { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_ban_from_community::dsl::*; mod_ban_from_community.find(from_id).first::(conn) @@ -136,7 +136,7 @@ impl Crud for ModBanFromCommunity { } } -impl Crud for ModBan { +impl Crud for ModBan { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_ban::dsl::*; mod_ban.find(from_id).first::(conn) @@ -155,7 +155,7 @@ impl Crud for ModBan { } } -impl Crud for ModAddCommunity { +impl Crud for ModAddCommunity { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_add_community::dsl::*; mod_add_community.find(from_id).first::(conn) @@ -176,7 +176,7 @@ impl Crud for ModAddCommunity { } } -impl Crud for ModAdd { +impl Crud for ModAdd { fn read(conn: &PgConnection, from_id: i32) -> Result { use lemmy_db_schema::schema::mod_add::dsl::*; mod_add.find(from_id).first::(conn) @@ -197,8 +197,8 @@ impl Crud for ModAdd { #[cfg(test)] mod tests { - use crate::{establish_unpooled_connection, Crud, ListingType, SortType}; - use lemmy_db_schema::source::{comment::*, community::*, moderator::*, post::*, user::*}; + use crate::{establish_unpooled_connection, Crud}; + use lemmy_db_schema::source::{comment::*, community::*, moderator::*, person::*, post::*}; use serial_test::serial; // use Crud; @@ -207,28 +207,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_mod = UserForm { + let new_mod = PersonForm { name: "the mod".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -236,30 +226,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -267,13 +247,13 @@ mod tests { 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 { name: "mod_community".to_string(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -297,7 +277,7 @@ mod tests { name: "A test post thweep".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -318,7 +298,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -336,7 +316,7 @@ mod tests { // remove post let mod_remove_post_form = ModRemovePostForm { - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, post_id: inserted_post.id, reason: None, removed: None, @@ -346,7 +326,7 @@ mod tests { let expected_mod_remove_post = ModRemovePost { id: inserted_mod_remove_post.id, post_id: inserted_post.id, - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, reason: None, removed: Some(true), when_: inserted_mod_remove_post.when_, @@ -355,7 +335,7 @@ mod tests { // lock post let mod_lock_post_form = ModLockPostForm { - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, post_id: inserted_post.id, locked: None, }; @@ -364,7 +344,7 @@ mod tests { let expected_mod_lock_post = ModLockPost { id: inserted_mod_lock_post.id, post_id: inserted_post.id, - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, locked: Some(true), when_: inserted_mod_lock_post.when_, }; @@ -372,7 +352,7 @@ mod tests { // sticky post let mod_sticky_post_form = ModStickyPostForm { - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, post_id: inserted_post.id, stickied: None, }; @@ -381,7 +361,7 @@ mod tests { let expected_mod_sticky_post = ModStickyPost { id: inserted_mod_sticky_post.id, post_id: inserted_post.id, - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, stickied: Some(true), when_: inserted_mod_sticky_post.when_, }; @@ -389,7 +369,7 @@ mod tests { // comment let mod_remove_comment_form = ModRemoveCommentForm { - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, comment_id: inserted_comment.id, reason: None, removed: None, @@ -401,7 +381,7 @@ mod tests { let expected_mod_remove_comment = ModRemoveComment { id: inserted_mod_remove_comment.id, comment_id: inserted_comment.id, - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, reason: None, removed: Some(true), when_: inserted_mod_remove_comment.when_, @@ -410,7 +390,7 @@ mod tests { // community let mod_remove_community_form = ModRemoveCommunityForm { - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, community_id: inserted_community.id, reason: None, removed: None, @@ -423,7 +403,7 @@ mod tests { let expected_mod_remove_community = ModRemoveCommunity { id: inserted_mod_remove_community.id, community_id: inserted_community.id, - mod_user_id: inserted_mod.id, + mod_person_id: inserted_mod.id, reason: None, removed: Some(true), expires: None, @@ -433,8 +413,8 @@ mod tests { // ban from community let mod_ban_from_community_form = ModBanFromCommunityForm { - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, community_id: inserted_community.id, reason: None, banned: None, @@ -447,8 +427,8 @@ mod tests { let expected_mod_ban_from_community = ModBanFromCommunity { id: inserted_mod_ban_from_community.id, community_id: inserted_community.id, - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, reason: None, banned: Some(true), expires: None, @@ -458,8 +438,8 @@ mod tests { // ban let mod_ban_form = ModBanForm { - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, reason: None, banned: None, expires: None, @@ -468,8 +448,8 @@ mod tests { let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap(); let expected_mod_ban = ModBan { id: inserted_mod_ban.id, - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, reason: None, banned: Some(true), expires: None, @@ -479,8 +459,8 @@ mod tests { // mod add community let mod_add_community_form = ModAddCommunityForm { - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, community_id: inserted_community.id, removed: None, }; @@ -491,8 +471,8 @@ mod tests { let expected_mod_add_community = ModAddCommunity { id: inserted_mod_add_community.id, community_id: inserted_community.id, - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, removed: Some(false), when_: inserted_mod_add_community.when_, }; @@ -500,16 +480,16 @@ mod tests { // mod add let mod_add_form = ModAddForm { - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, removed: None, }; let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap(); let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap(); let expected_mod_add = ModAdd { id: inserted_mod_add.id, - mod_user_id: inserted_mod.id, - other_user_id: inserted_user.id, + mod_person_id: inserted_mod.id, + other_person_id: inserted_person.id, removed: Some(false), when_: inserted_mod_add.when_, }; @@ -517,8 +497,8 @@ mod tests { Comment::delete(&conn, inserted_comment.id).unwrap(); Post::delete(&conn, inserted_post.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap(); - User_::delete(&conn, inserted_user.id).unwrap(); - User_::delete(&conn, inserted_mod.id).unwrap(); + Person::delete(&conn, inserted_person.id).unwrap(); + Person::delete(&conn, inserted_mod.id).unwrap(); assert_eq!(expected_mod_remove_post, read_mod_remove_post); assert_eq!(expected_mod_lock_post, read_mod_lock_post); diff --git a/crates/db_queries/src/source/password_reset_request.rs b/crates/db_queries/src/source/password_reset_request.rs index 600037d8a..89c375058 100644 --- a/crates/db_queries/src/source/password_reset_request.rs +++ b/crates/db_queries/src/source/password_reset_request.rs @@ -1,9 +1,13 @@ use crate::Crud; 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}; -impl Crud for PasswordResetRequest { +impl Crud for PasswordResetRequest { fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result { password_reset_request .find(password_reset_request_id) @@ -28,7 +32,7 @@ impl Crud for PasswordResetRequest { pub trait PasswordResetRequest_ { fn create_token( conn: &PgConnection, - from_user_id: i32, + from_local_user_id: LocalUserId, token: &str, ) -> Result; fn read_from_token(conn: &PgConnection, token: &str) -> Result; @@ -37,7 +41,7 @@ pub trait PasswordResetRequest_ { impl PasswordResetRequest_ for PasswordResetRequest { fn create_token( conn: &PgConnection, - from_user_id: i32, + from_local_user_id: LocalUserId, token: &str, ) -> Result { 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 form = PasswordResetRequestForm { - user_id: from_user_id, + local_user_id: from_local_user_id, token_encrypted: token_hash, }; @@ -76,10 +80,12 @@ mod tests { establish_unpooled_connection, source::password_reset_request::PasswordResetRequest_, 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; #[test] @@ -87,28 +93,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "thommy prw".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -116,23 +112,40 @@ mod tests { 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_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce"; 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 { id: inserted_password_reset_request.id, - user_id: inserted_user.id, + local_user_id: inserted_local_user.id, token_encrypted: token_encrypted_.to_string(), published: inserted_password_reset_request.published, }; 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!( diff --git a/crates/db_queries/src/source/person.rs b/crates/db_queries/src/source/person.rs new file mode 100644 index 000000000..f9979c970 --- /dev/null +++ b/crates/db_queries/src/source/person.rs @@ -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 for Person { + fn read(conn: &PgConnection, person_id: PersonId) -> Result { + person + .filter(deleted.eq(false)) + .find(person_id) + .first::(conn) + } + fn delete(conn: &PgConnection, person_id: PersonId) -> Result { + diesel::delete(person.find(person_id)).execute(conn) + } + fn create(conn: &PgConnection, form: &PersonForm) -> Result { + insert_into(person).values(form).get_result::(conn) + } + fn update(conn: &PgConnection, person_id: PersonId, form: &PersonForm) -> Result { + diesel::update(person.find(person_id)) + .set(form) + .get_result::(conn) + } +} + +impl ApubObject for Person { + fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result { + use lemmy_db_schema::schema::person::dsl::*; + person + .filter(deleted.eq(false)) + .filter(actor_id.eq(object_id)) + .first::(conn) + } + + fn upsert(conn: &PgConnection, person_form: &PersonForm) -> Result { + insert_into(person) + .values(person_form) + .on_conflict(actor_id) + .do_update() + .set(person_form) + .get_result::(conn) + } +} + +pub trait Person_ { + fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result; + fn find_by_name(conn: &PgConnection, name: &str) -> Result; + fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result; + fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result; +} + +impl Person_ for Person { + fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result { + diesel::update(person.find(person_id)) + .set(banned.eq(ban)) + .get_result::(conn) + } + + fn find_by_name(conn: &PgConnection, from_name: &str) -> Result { + person + .filter(deleted.eq(false)) + .filter(local.eq(true)) + .filter(name.ilike(from_name)) + .first::(conn) + } + + fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result { + diesel::update(person.find(person_id)) + .set((last_refreshed_at.eq(naive_now()),)) + .get_result::(conn) + } + + fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result { + 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::>(None), + local_user::matrix_user_id.eq::>(None), + )) + .execute(conn)?; + + diesel::update(person.find(person_id)) + .set(( + preferred_username.eq::>(None), + bio.eq::>(None), + deleted.eq(true), + updated.eq(naive_now()), + )) + .get_result::(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); + } +} diff --git a/crates/db_queries/src/source/user_mention.rs b/crates/db_queries/src/source/person_mention.rs similarity index 57% rename from crates/db_queries/src/source/user_mention.rs rename to crates/db_queries/src/source/person_mention.rs index 5efc95bf6..dfd626cba 100644 --- a/crates/db_queries/src/source/user_mention.rs +++ b/crates/db_queries/src/source/person_mention.rs @@ -1,68 +1,68 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; -use lemmy_db_schema::source::user_mention::*; +use lemmy_db_schema::{source::person_mention::*, PersonId, PersonMentionId}; -impl Crud for UserMention { - fn read(conn: &PgConnection, user_mention_id: i32) -> Result { - use lemmy_db_schema::schema::user_mention::dsl::*; - user_mention.find(user_mention_id).first::(conn) +impl Crud for PersonMention { + fn read(conn: &PgConnection, person_mention_id: PersonMentionId) -> Result { + use lemmy_db_schema::schema::person_mention::dsl::*; + person_mention.find(person_mention_id).first::(conn) } - fn create(conn: &PgConnection, user_mention_form: &UserMentionForm) -> Result { - use lemmy_db_schema::schema::user_mention::dsl::*; + fn create(conn: &PgConnection, person_mention_form: &PersonMentionForm) -> Result { + use lemmy_db_schema::schema::person_mention::dsl::*; // since the return here isnt utilized, we dont need to do an update // but get_result doesnt return the existing row here - insert_into(user_mention) - .values(user_mention_form) + insert_into(person_mention) + .values(person_mention_form) .on_conflict((recipient_id, comment_id)) .do_update() - .set(user_mention_form) + .set(person_mention_form) .get_result::(conn) } fn update( conn: &PgConnection, - user_mention_id: i32, - user_mention_form: &UserMentionForm, + person_mention_id: PersonMentionId, + person_mention_form: &PersonMentionForm, ) -> Result { - use lemmy_db_schema::schema::user_mention::dsl::*; - diesel::update(user_mention.find(user_mention_id)) - .set(user_mention_form) + use lemmy_db_schema::schema::person_mention::dsl::*; + diesel::update(person_mention.find(person_mention_id)) + .set(person_mention_form) .get_result::(conn) } } -pub trait UserMention_ { +pub trait PersonMention_ { fn update_read( conn: &PgConnection, - user_mention_id: i32, + person_mention_id: PersonMentionId, new_read: bool, - ) -> Result; + ) -> Result; fn mark_all_as_read( conn: &PgConnection, - for_recipient_id: i32, - ) -> Result, Error>; + for_recipient_id: PersonId, + ) -> Result, Error>; } -impl UserMention_ for UserMention { +impl PersonMention_ for PersonMention { fn update_read( conn: &PgConnection, - user_mention_id: i32, + person_mention_id: PersonMentionId, new_read: bool, - ) -> Result { - use lemmy_db_schema::schema::user_mention::dsl::*; - diesel::update(user_mention.find(user_mention_id)) + ) -> Result { + use lemmy_db_schema::schema::person_mention::dsl::*; + diesel::update(person_mention.find(person_mention_id)) .set(read.eq(new_read)) .get_result::(conn) } fn mark_all_as_read( conn: &PgConnection, - for_recipient_id: i32, - ) -> Result, Error> { - use lemmy_db_schema::schema::user_mention::dsl::*; + for_recipient_id: PersonId, + ) -> Result, Error> { + use lemmy_db_schema::schema::person_mention::dsl::*; diesel::update( - user_mention + person_mention .filter(recipient_id.eq(for_recipient_id)) .filter(read.eq(false)), ) @@ -73,13 +73,13 @@ impl UserMention_ for UserMention { #[cfg(test)] mod tests { - use crate::{establish_unpooled_connection, Crud, ListingType, SortType}; + use crate::{establish_unpooled_connection, Crud}; use lemmy_db_schema::source::{ comment::*, community::{Community, CommunityForm}, + person::*, + person_mention::*, post::*, - user::*, - user_mention::*, }; use serial_test::serial; @@ -88,28 +88,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "terrylake".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -117,30 +107,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -148,13 +128,13 @@ mod tests { 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 { name: "test community lake".to_string(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -176,7 +156,7 @@ mod tests { let new_post = PostForm { name: "A test post".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, url: None, body: None, community_id: inserted_community.id, @@ -199,7 +179,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, removed: None, deleted: None, @@ -213,15 +193,15 @@ mod tests { let inserted_comment = Comment::create(&conn, &comment_form).unwrap(); - let user_mention_form = UserMentionForm { + let person_mention_form = PersonMentionForm { recipient_id: inserted_recipient.id, comment_id: inserted_comment.id, 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, recipient_id: inserted_mention.recipient_id, comment_id: inserted_mention.comment_id, @@ -229,14 +209,14 @@ mod tests { 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 = - 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(); Post::delete(&conn, inserted_post.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap(); - User_::delete(&conn, inserted_user.id).unwrap(); - User_::delete(&conn, inserted_recipient.id).unwrap(); + Person::delete(&conn, inserted_person.id).unwrap(); + Person::delete(&conn, inserted_recipient.id).unwrap(); assert_eq!(expected_mention, read_mention); assert_eq!(expected_mention, inserted_mention); diff --git a/crates/db_queries/src/source/post.rs b/crates/db_queries/src/source/post.rs index f105dc738..d6492e130 100644 --- a/crates/db_queries/src/source/post.rs +++ b/crates/db_queries/src/source/post.rs @@ -12,16 +12,19 @@ use lemmy_db_schema::{ PostSaved, PostSavedForm, }, + CommunityId, DbUrl, + PersonId, + PostId, }; -impl Crud for Post { - fn read(conn: &PgConnection, post_id: i32) -> Result { +impl Crud for Post { + fn read(conn: &PgConnection, post_id: PostId) -> Result { use lemmy_db_schema::schema::post::dsl::*; post.find(post_id).first::(conn) } - fn delete(conn: &PgConnection, post_id: i32) -> Result { + fn delete(conn: &PgConnection, post_id: PostId) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::delete(post.find(post_id)).execute(conn) } @@ -31,7 +34,7 @@ impl Crud for Post { insert_into(post).values(new_post).get_result::(conn) } - fn update(conn: &PgConnection, post_id: i32, new_post: &PostForm) -> Result { + fn update(conn: &PgConnection, post_id: PostId, new_post: &PostForm) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) .set(new_post) @@ -41,24 +44,39 @@ impl Crud for Post { pub trait Post_ { //fn read(conn: &PgConnection, post_id: i32) -> Result; - fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result, Error>; - fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: DbUrl) -> Result; - fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result, Error>; - fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result; - fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result; + fn list_for_community( + conn: &PgConnection, + the_community_id: CommunityId, + ) -> Result, Error>; + fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result; + fn permadelete_for_creator( + conn: &PgConnection, + for_creator_id: PersonId, + ) -> Result, Error>; + fn update_deleted(conn: &PgConnection, post_id: PostId, new_deleted: bool) + -> Result; + fn update_removed(conn: &PgConnection, post_id: PostId, new_removed: bool) + -> Result; fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, - for_community_id: Option, + for_creator_id: PersonId, + for_community_id: Option, new_removed: bool, ) -> Result, Error>; - fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result; - fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result; - fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool; + fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result; + fn update_stickied( + conn: &PgConnection, + post_id: PostId, + new_stickied: bool, + ) -> Result; + fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool; } impl Post_ for Post { - fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result, Error> { + fn list_for_community( + conn: &PgConnection, + the_community_id: CommunityId, + ) -> Result, Error> { use lemmy_db_schema::schema::post::dsl::*; post .filter(community_id.eq(the_community_id)) @@ -68,7 +86,7 @@ impl Post_ for Post { .load::(conn) } - fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: DbUrl) -> Result { + fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) @@ -76,7 +94,10 @@ impl Post_ for Post { .get_result::(conn) } - fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result, Error> { + fn permadelete_for_creator( + conn: &PgConnection, + for_creator_id: PersonId, + ) -> Result, Error> { use lemmy_db_schema::schema::post::dsl::*; let perma_deleted = "*Permananently Deleted*"; @@ -93,14 +114,22 @@ impl Post_ for Post { .get_results::(conn) } - fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result { + fn update_deleted( + conn: &PgConnection, + post_id: PostId, + new_deleted: bool, + ) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) .set((deleted.eq(new_deleted), updated.eq(naive_now()))) .get_result::(conn) } - fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result { + fn update_removed( + conn: &PgConnection, + post_id: PostId, + new_removed: bool, + ) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) .set((removed.eq(new_removed), updated.eq(naive_now()))) @@ -109,8 +138,8 @@ impl Post_ for Post { fn update_removed_for_creator( conn: &PgConnection, - for_creator_id: i32, - for_community_id: Option, + for_creator_id: PersonId, + for_community_id: Option, new_removed: bool, ) -> Result, Error> { use lemmy_db_schema::schema::post::dsl::*; @@ -127,22 +156,26 @@ impl Post_ for Post { .get_results::(conn) } - fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result { + fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) .set(locked.eq(new_locked)) .get_result::(conn) } - fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result { + fn update_stickied( + conn: &PgConnection, + post_id: PostId, + new_stickied: bool, + ) -> Result { use lemmy_db_schema::schema::post::dsl::*; diesel::update(post.find(post_id)) .set(stickied.eq(new_stickied)) .get_result::(conn) } - fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool { - user_id == post_creator_id + fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool { + person_id == post_creator_id } } @@ -163,22 +196,22 @@ impl ApubObject for Post { } } -impl Likeable for PostLike { +impl Likeable for PostLike { fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result { use lemmy_db_schema::schema::post_like::dsl::*; insert_into(post_like) .values(post_like_form) - .on_conflict((post_id, user_id)) + .on_conflict((post_id, person_id)) .do_update() .set(post_like_form) .get_result::(conn) } - fn remove(conn: &PgConnection, user_id: i32, post_id: i32) -> Result { + fn remove(conn: &PgConnection, person_id: PersonId, post_id: PostId) -> Result { use lemmy_db_schema::schema::post_like::dsl; diesel::delete( dsl::post_like .filter(dsl::post_id.eq(post_id)) - .filter(dsl::user_id.eq(user_id)), + .filter(dsl::person_id.eq(person_id)), ) .execute(conn) } @@ -189,7 +222,7 @@ impl Saveable for PostSaved { use lemmy_db_schema::schema::post_saved::dsl::*; insert_into(post_saved) .values(post_saved_form) - .on_conflict((post_id, user_id)) + .on_conflict((post_id, person_id)) .do_update() .set(post_saved_form) .get_result::(conn) @@ -199,7 +232,7 @@ impl Saveable for PostSaved { diesel::delete( post_saved .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) } @@ -218,7 +251,7 @@ impl Readable for PostRead { diesel::delete( post_read .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) } @@ -226,10 +259,10 @@ impl Readable for PostRead { #[cfg(test)] mod tests { - use crate::{establish_unpooled_connection, source::post::*, ListingType, SortType}; + use crate::{establish_unpooled_connection, source::post::*}; use lemmy_db_schema::source::{ community::{Community, CommunityForm}, - user::*, + person::*, }; use serial_test::serial; @@ -238,28 +271,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "jim".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -267,13 +290,13 @@ mod tests { 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 { name: "test community_3".to_string(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -297,7 +320,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -321,7 +344,7 @@ mod tests { name: "A test post".into(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, published: inserted_post.published, removed: false, @@ -341,7 +364,7 @@ mod tests { // Post Like let post_like_form = PostLikeForm { post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -350,7 +373,7 @@ mod tests { let expected_post_like = PostLike { id: inserted_post_like.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_post_like.published, score: 1, }; @@ -358,7 +381,7 @@ mod tests { // Post Save let post_saved_form = PostSavedForm { 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(); @@ -366,14 +389,14 @@ mod tests { let expected_post_saved = PostSaved { id: inserted_post_saved.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_post_saved.published, }; // Post Read let post_read_form = PostReadForm { 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(); @@ -381,18 +404,18 @@ mod tests { let expected_post_read = PostRead { id: inserted_post_read.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_post_read.published, }; let read_post = Post::read(&conn, inserted_post.id).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 read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap(); let num_deleted = Post::delete(&conn, inserted_post.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, inserted_post); diff --git a/crates/db_queries/src/source/post_report.rs b/crates/db_queries/src/source/post_report.rs index e81dc7c04..b4e855731 100644 --- a/crates/db_queries/src/source/post_report.rs +++ b/crates/db_queries/src/source/post_report.rs @@ -1,6 +1,6 @@ use crate::Reportable; 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 for PostReport { /// creates a post report and returns it @@ -19,7 +19,11 @@ impl Reportable for PostReport { /// * `conn` - the postgres connection /// * `report_id` - the id of the report to resolve /// * `by_resolver_id` - the id of the user resolving the report - fn resolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result { + fn resolve( + conn: &PgConnection, + report_id: i32, + by_resolver_id: PersonId, + ) -> Result { use lemmy_db_schema::schema::post_report::dsl::*; update(post_report.find(report_id)) .set(( @@ -35,7 +39,11 @@ impl Reportable for PostReport { /// * `conn` - the postgres connection /// * `report_id` - the id of the report to unresolve /// * `by_resolver_id` - the id of the user unresolving the report - fn unresolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result { + fn unresolve( + conn: &PgConnection, + report_id: i32, + by_resolver_id: PersonId, + ) -> Result { use lemmy_db_schema::schema::post_report::dsl::*; update(post_report.find(report_id)) .set(( diff --git a/crates/db_queries/src/source/private_message.rs b/crates/db_queries/src/source/private_message.rs index c437252ef..fe2456890 100644 --- a/crates/db_queries/src/source/private_message.rs +++ b/crates/db_queries/src/source/private_message.rs @@ -1,9 +1,9 @@ use crate::{ApubObject, Crud}; use diesel::{dsl::*, result::Error, *}; -use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl}; +use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl, PersonId, PrivateMessageId}; -impl Crud for PrivateMessage { - fn read(conn: &PgConnection, private_message_id: i32) -> Result { +impl Crud for PrivateMessage { + fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; private_message.find(private_message_id).first::(conn) } @@ -17,7 +17,7 @@ impl Crud for PrivateMessage { fn update( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, private_message_form: &PrivateMessageForm, ) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; @@ -52,34 +52,34 @@ impl ApubObject for PrivateMessage { pub trait PrivateMessage_ { fn update_ap_id( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, apub_id: DbUrl, ) -> Result; fn update_content( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_content: &str, ) -> Result; fn update_deleted( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_deleted: bool, ) -> Result; fn update_read( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_read: bool, ) -> Result; fn mark_all_as_read( conn: &PgConnection, - for_recipient_id: i32, + for_recipient_id: PersonId, ) -> Result, Error>; } impl PrivateMessage_ for PrivateMessage { fn update_ap_id( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, apub_id: DbUrl, ) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; @@ -91,7 +91,7 @@ impl PrivateMessage_ for PrivateMessage { fn update_content( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_content: &str, ) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; @@ -102,7 +102,7 @@ impl PrivateMessage_ for PrivateMessage { fn update_deleted( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_deleted: bool, ) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; @@ -113,7 +113,7 @@ impl PrivateMessage_ for PrivateMessage { fn update_read( conn: &PgConnection, - private_message_id: i32, + private_message_id: PrivateMessageId, new_read: bool, ) -> Result { use lemmy_db_schema::schema::private_message::dsl::*; @@ -124,7 +124,7 @@ impl PrivateMessage_ for PrivateMessage { fn mark_all_as_read( conn: &PgConnection, - for_recipient_id: i32, + for_recipient_id: PersonId, ) -> Result, Error> { use lemmy_db_schema::schema::private_message::dsl::*; diesel::update( @@ -139,14 +139,8 @@ impl PrivateMessage_ for PrivateMessage { #[cfg(test)] mod tests { - use crate::{ - establish_unpooled_connection, - source::private_message::PrivateMessage_, - Crud, - ListingType, - SortType, - }; - use lemmy_db_schema::source::{private_message::*, user::*}; + use crate::{establish_unpooled_connection, source::private_message::PrivateMessage_, Crud}; + use lemmy_db_schema::source::{person::*, private_message::*}; use serial_test::serial; #[test] @@ -154,28 +148,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let creator_form = UserForm { + let creator_form = PersonForm { name: "creator_pm".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -183,30 +167,20 @@ mod tests { 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(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -214,7 +188,7 @@ mod tests { 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 { content: "A test private message".into(), @@ -250,8 +224,8 @@ mod tests { PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap(); let marked_read_private_message = PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap(); - User_::delete(&conn, inserted_creator.id).unwrap(); - User_::delete(&conn, inserted_recipient.id).unwrap(); + Person::delete(&conn, inserted_creator.id).unwrap(); + Person::delete(&conn, inserted_recipient.id).unwrap(); assert_eq!(expected_private_message, read_private_message); assert_eq!(expected_private_message, updated_private_message); diff --git a/crates/db_queries/src/source/site.rs b/crates/db_queries/src/source/site.rs index 2510f46c9..d688546f8 100644 --- a/crates/db_queries/src/source/site.rs +++ b/crates/db_queries/src/source/site.rs @@ -1,8 +1,8 @@ use crate::Crud; use diesel::{dsl::*, result::Error, *}; -use lemmy_db_schema::{naive_now, source::site::*}; +use lemmy_db_schema::{naive_now, source::site::*, PersonId}; -impl Crud for Site { +impl Crud for Site { fn read(conn: &PgConnection, _site_id: i32) -> Result { use lemmy_db_schema::schema::site::dsl::*; site.first::(conn) @@ -26,12 +26,12 @@ impl Crud for Site { } pub trait Site_ { - fn transfer(conn: &PgConnection, new_creator_id: i32) -> Result; + fn transfer(conn: &PgConnection, new_creator_id: PersonId) -> Result; fn read_simple(conn: &PgConnection) -> Result; } impl Site_ for Site { - fn transfer(conn: &PgConnection, new_creator_id: i32) -> Result { + fn transfer(conn: &PgConnection, new_creator_id: PersonId) -> Result { use lemmy_db_schema::schema::site::dsl::*; diesel::update(site.find(1)) .set((creator_id.eq(new_creator_id), updated.eq(naive_now()))) diff --git a/crates/db_queries/src/source/user.rs b/crates/db_queries/src/source/user.rs deleted file mode 100644 index d0e7411a5..000000000 --- a/crates/db_queries/src/source/user.rs +++ /dev/null @@ -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_}, - DbUrl, -}; -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; -} - -impl UserSafeSettings_ for UserSafeSettings { - fn read(conn: &PgConnection, user_id: i32) -> Result { - user_ - .select(User_::safe_settings_columns_tuple()) - .filter(deleted.eq(false)) - .find(user_id) - .first::(conn) - } -} - -impl Crud for User_ { - fn read(conn: &PgConnection, user_id: i32) -> Result { - user_ - .filter(deleted.eq(false)) - .find(user_id) - .first::(conn) - } - fn delete(conn: &PgConnection, user_id: i32) -> Result { - diesel::delete(user_.find(user_id)).execute(conn) - } - fn create(conn: &PgConnection, form: &UserForm) -> Result { - insert_into(user_).values(form).get_result::(conn) - } - fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result { - diesel::update(user_.find(user_id)) - .set(form) - .get_result::(conn) - } -} - -impl ApubObject for User_ { - fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result { - use lemmy_db_schema::schema::user_::dsl::*; - user_ - .filter(deleted.eq(false)) - .filter(actor_id.eq(object_id)) - .first::(conn) - } - - fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result { - insert_into(user_) - .values(user_form) - .on_conflict(actor_id) - .do_update() - .set(user_form) - .get_result::(conn) - } -} - -pub trait User { - fn register(conn: &PgConnection, form: &UserForm) -> Result; - fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) - -> Result; - fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result; - fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result; - fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result; - fn find_by_email_or_username( - conn: &PgConnection, - username_or_email: &str, - ) -> Result; - fn find_by_username(conn: &PgConnection, username: &str) -> Result; - fn find_by_email(conn: &PgConnection, from_email: &str) -> Result; - fn get_profile_url(&self, hostname: &str) -> String; - fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result; - fn delete_account(conn: &PgConnection, user_id: i32) -> Result; -} - -impl User for User_ { - fn register(conn: &PgConnection, form: &UserForm) -> Result { - 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 { - 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::(conn) - } - - fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result { - user_ - .filter(local.eq(true)) - .filter(deleted.eq(false)) - .filter(name.eq(from_user_name)) - .first::(conn) - } - - fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result { - diesel::update(user_.find(user_id)) - .set(admin.eq(added)) - .get_result::(conn) - } - - fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result { - diesel::update(user_.find(user_id)) - .set(banned.eq(ban)) - .get_result::(conn) - } - - fn find_by_email_or_username( - conn: &PgConnection, - username_or_email: &str, - ) -> Result { - 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_ - .filter(deleted.eq(false)) - .filter(local.eq(true)) - .filter(name.ilike(username)) - .first::(conn) - } - - fn find_by_email(conn: &PgConnection, from_email: &str) -> Result { - user_ - .filter(deleted.eq(false)) - .filter(local.eq(true)) - .filter(email.eq(from_email)) - .first::(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 { - diesel::update(user_.find(user_id)) - .set((last_refreshed_at.eq(naive_now()),)) - .get_result::(conn) - } - - fn delete_account(conn: &PgConnection, user_id: i32) -> Result { - diesel::update(user_.find(user_id)) - .set(( - preferred_username.eq::>(None), - email.eq::>(None), - matrix_user_id.eq::>(None), - bio.eq::>(None), - deleted.eq(true), - updated.eq(naive_now()), - )) - .get_result::(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); - } -} diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index 1da8b68fb..70f3364e5 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -13,3 +13,4 @@ serde = { version = "1.0.123", features = ["derive"] } serde_json = { version = "1.0.61", features = ["preserve_order"] } log = "0.4.14" url = { version = "2.2.1", features = ["serde"] } +diesel-derive-newtype = "0.1" diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index f44567b90..6b07e5cee 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -1,6 +1,9 @@ #[macro_use] extern crate diesel; +#[macro_use] +extern crate diesel_derive_newtype; + use chrono::NaiveDateTime; use diesel::{ backend::Backend, @@ -10,6 +13,7 @@ use diesel::{ }; use serde::{Deserialize, Serialize}; use std::{ + fmt, fmt::{Display, Formatter}, io::Write, }; @@ -18,6 +22,45 @@ use url::Url; pub mod schema; pub mod source; +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)] +pub struct PostId(pub i32); + +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"] diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 3786e00ca..c5bf7d2fe 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -41,7 +41,7 @@ table! { table! { comment_like (id) { id -> Int4, - user_id -> Int4, + person_id -> Int4, comment_id -> Int4, post_id -> Int4, score -> Int2, @@ -67,7 +67,7 @@ table! { comment_saved (id) { id -> Int4, comment_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, } } @@ -89,11 +89,11 @@ table! { private_key -> Nullable, public_key -> Nullable, last_refreshed_at -> Timestamp, - icon -> Nullable, - banner -> Nullable, - followers_url -> Text, - inbox_url -> Text, - shared_inbox_url -> Nullable, + icon -> Nullable, + banner -> Nullable, + followers_url -> Varchar, + inbox_url -> Varchar, + shared_inbox_url -> Nullable, } } @@ -116,7 +116,7 @@ table! { community_follower (id) { id -> Int4, community_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, pending -> Nullable, } @@ -126,25 +126,43 @@ table! { community_moderator (id) { id -> Int4, community_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, } } table! { - community_user_ban (id) { + community_person_ban (id) { id -> Int4, community_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, } } +table! { + local_user (id) { + id -> Int4, + person_id -> Int4, + password_encrypted -> Text, + email -> Nullable, + 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, + } +} + table! { mod_add (id) { id -> Int4, - mod_user_id -> Int4, - other_user_id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, removed -> Nullable, when_ -> Timestamp, } @@ -153,8 +171,8 @@ table! { table! { mod_add_community (id) { id -> Int4, - mod_user_id -> Int4, - other_user_id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, community_id -> Int4, removed -> Nullable, when_ -> Timestamp, @@ -164,8 +182,8 @@ table! { table! { mod_ban (id) { id -> Int4, - mod_user_id -> Int4, - other_user_id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, reason -> Nullable, banned -> Nullable, expires -> Nullable, @@ -176,8 +194,8 @@ table! { table! { mod_ban_from_community (id) { id -> Int4, - mod_user_id -> Int4, - other_user_id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, community_id -> Int4, reason -> Nullable, banned -> Nullable, @@ -189,7 +207,7 @@ table! { table! { mod_lock_post (id) { id -> Int4, - mod_user_id -> Int4, + mod_person_id -> Int4, post_id -> Int4, locked -> Nullable, when_ -> Timestamp, @@ -199,7 +217,7 @@ table! { table! { mod_remove_comment (id) { id -> Int4, - mod_user_id -> Int4, + mod_person_id -> Int4, comment_id -> Int4, reason -> Nullable, removed -> Nullable, @@ -210,7 +228,7 @@ table! { table! { mod_remove_community (id) { id -> Int4, - mod_user_id -> Int4, + mod_person_id -> Int4, community_id -> Int4, reason -> Nullable, removed -> Nullable, @@ -222,7 +240,7 @@ table! { table! { mod_remove_post (id) { id -> Int4, - mod_user_id -> Int4, + mod_person_id -> Int4, post_id -> Int4, reason -> Nullable, removed -> Nullable, @@ -233,7 +251,7 @@ table! { table! { mod_sticky_post (id) { id -> Int4, - mod_user_id -> Int4, + mod_person_id -> Int4, post_id -> Int4, stickied -> Nullable, when_ -> Timestamp, @@ -243,9 +261,60 @@ table! { table! { password_reset_request (id) { id -> Int4, - user_id -> Int4, token_encrypted -> Text, published -> Timestamp, + local_user_id -> Int4, + } +} + +table! { + person (id) { + id -> Int4, + name -> Varchar, + preferred_username -> Nullable, + avatar -> Nullable, + banned -> Bool, + published -> Timestamp, + updated -> Nullable, + actor_id -> Varchar, + bio -> Nullable, + local -> Bool, + private_key -> Nullable, + public_key -> Nullable, + last_refreshed_at -> Timestamp, + banner -> Nullable, + deleted -> Bool, + inbox_url -> Varchar, + shared_inbox_url -> Nullable, + } +} + +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 +322,7 @@ table! { post (id) { id -> Int4, name -> Varchar, - url -> Nullable, + url -> Nullable, body -> Nullable, creator_id -> Int4, community_id -> Int4, @@ -292,7 +361,7 @@ table! { post_like (id) { id -> Int4, post_id -> Int4, - user_id -> Int4, + person_id -> Int4, score -> Int2, published -> Timestamp, } @@ -302,7 +371,7 @@ table! { post_read (id) { id -> Int4, post_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, } } @@ -327,7 +396,7 @@ table! { post_saved (id) { id -> Int4, post_id -> Int4, - user_id -> Int4, + person_id -> Int4, published -> Timestamp, } } @@ -358,8 +427,8 @@ table! { enable_downvotes -> Bool, open_registration -> Bool, enable_nsfw -> Bool, - icon -> Nullable, - banner -> Nullable, + icon -> Nullable, + banner -> Nullable, } } @@ -378,68 +447,6 @@ table! { } } -table! { - user_ (id) { - id -> Int4, - name -> Varchar, - preferred_username -> Nullable, - password_encrypted -> Text, - email -> Nullable, - avatar -> Nullable, - admin -> Bool, - banned -> Bool, - published -> Timestamp, - updated -> Nullable, - 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, - actor_id -> Varchar, - bio -> Nullable, - local -> Bool, - private_key -> Nullable, - public_key -> Nullable, - last_refreshed_at -> Timestamp, - banner -> Nullable, - deleted -> Bool, - inbox_url -> Text, - shared_inbox_url -> Nullable, - } -} - -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 table! { comment_alias_1 (id) { @@ -459,122 +466,105 @@ table! { } table! { - user_alias_1 (id) { + person_alias_1 (id) { id -> Int4, name -> Varchar, preferred_username -> Nullable, - password_encrypted -> Text, - email -> Nullable, - avatar -> Nullable, - admin -> Bool, + avatar -> Nullable, banned -> Bool, published -> Timestamp, updated -> Nullable, - 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, actor_id -> Varchar, bio -> Nullable, local -> Bool, private_key -> Nullable, public_key -> Nullable, last_refreshed_at -> Timestamp, - banner -> Nullable, + banner -> Nullable, deleted -> Bool, + inbox_url -> Varchar, + shared_inbox_url -> Nullable, } } table! { - user_alias_2 (id) { + person_alias_2 (id) { id -> Int4, name -> Varchar, preferred_username -> Nullable, - password_encrypted -> Text, - email -> Nullable, - avatar -> Nullable, - admin -> Bool, + avatar -> Nullable, banned -> Bool, published -> Timestamp, updated -> Nullable, - 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, actor_id -> Varchar, bio -> Nullable, local -> Bool, private_key -> Nullable, public_key -> Nullable, last_refreshed_at -> Timestamp, - banner -> Nullable, + banner -> Nullable, deleted -> Bool, + inbox_url -> Varchar, + shared_inbox_url -> Nullable, } } -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!(user_mention -> user_alias_1 (recipient_id)); -joinable!(post -> user_alias_1 (creator_id)); -joinable!(comment -> user_alias_1 (creator_id)); +joinable!(person_mention -> person_alias_1 (recipient_id)); +joinable!(post -> person_alias_1 (creator_id)); +joinable!(comment -> person_alias_1 (creator_id)); -joinable!(post_report -> user_alias_2 (resolver_id)); -joinable!(comment_report -> user_alias_2 (resolver_id)); +joinable!(post_report -> person_alias_2 (resolver_id)); +joinable!(comment_report -> person_alias_2 (resolver_id)); +joinable!(comment -> person (creator_id)); joinable!(comment -> post (post_id)); -joinable!(comment -> user_ (creator_id)); joinable!(comment_aggregates -> comment (comment_id)); joinable!(comment_like -> comment (comment_id)); +joinable!(comment_like -> person (person_id)); joinable!(comment_like -> post (post_id)); -joinable!(comment_like -> user_ (user_id)); joinable!(comment_report -> comment (comment_id)); joinable!(comment_saved -> comment (comment_id)); -joinable!(comment_saved -> user_ (user_id)); -joinable!(community -> user_ (creator_id)); +joinable!(comment_saved -> person (person_id)); +joinable!(community -> person (creator_id)); joinable!(community_aggregates -> 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 -> user_ (user_id)); -joinable!(community_user_ban -> community (community_id)); -joinable!(community_user_ban -> user_ (user_id)); +joinable!(community_moderator -> person (person_id)); +joinable!(community_person_ban -> community (community_id)); +joinable!(community_person_ban -> person (person_id)); +joinable!(local_user -> person (person_id)); joinable!(mod_add_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 -> user_ (mod_user_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 -> 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 -> user_ (mod_user_id)); +joinable!(mod_sticky_post -> person (mod_person_id)); joinable!(mod_sticky_post -> post (post_id)); -joinable!(mod_sticky_post -> user_ (mod_user_id)); -joinable!(password_reset_request -> user_ (user_id)); +joinable!(password_reset_request -> local_user (local_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 -> user_ (creator_id)); +joinable!(post -> person (creator_id)); joinable!(post_aggregates -> post (post_id)); +joinable!(post_like -> person (person_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 -> user_ (user_id)); joinable!(post_report -> post (post_id)); +joinable!(post_saved -> person (person_id)); joinable!(post_saved -> post (post_id)); -joinable!(post_saved -> user_ (user_id)); -joinable!(site -> user_ (creator_id)); +joinable!(site -> person (creator_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!( activity, @@ -587,7 +577,8 @@ allow_tables_to_appear_in_same_query!( community_aggregates, community_follower, community_moderator, - community_user_ban, + community_person_ban, + local_user, mod_add, mod_add_community, mod_ban, @@ -598,6 +589,10 @@ allow_tables_to_appear_in_same_query!( mod_remove_post, mod_sticky_post, password_reset_request, + person, + person_aggregates, + person_ban, + person_mention, post, post_aggregates, post_like, @@ -607,11 +602,7 @@ allow_tables_to_appear_in_same_query!( private_message, site, site_aggregates, - user_, - user_aggregates, - user_ban, - user_mention, comment_alias_1, - user_alias_1, - user_alias_2, + person_alias_1, + person_alias_2, ); diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index a00738a06..8a91f601e 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -1,7 +1,10 @@ use crate::{ schema::{comment, comment_alias_1, comment_like, comment_saved}, source::post::Post, + CommentId, DbUrl, + PersonId, + PostId, }; use serde::Serialize; @@ -16,10 +19,10 @@ use serde::Serialize; #[belongs_to(Post)] #[table_name = "comment"] pub struct Comment { - pub id: i32, - pub creator_id: i32, - pub post_id: i32, - pub parent_id: Option, + pub id: CommentId, + pub creator_id: PersonId, + pub post_id: PostId, + pub parent_id: Option, pub content: String, pub removed: bool, pub read: bool, // Whether the recipient has read the comment or not @@ -34,10 +37,10 @@ pub struct Comment { #[belongs_to(Post)] #[table_name = "comment_alias_1"] pub struct CommentAlias1 { - pub id: i32, - pub creator_id: i32, - pub post_id: i32, - pub parent_id: Option, + pub id: CommentId, + pub creator_id: PersonId, + pub post_id: PostId, + pub parent_id: Option, pub content: String, pub removed: bool, pub read: bool, // Whether the recipient has read the comment or not @@ -51,9 +54,9 @@ pub struct CommentAlias1 { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "comment"] pub struct CommentForm { - pub creator_id: i32, - pub post_id: i32, - pub parent_id: Option, + pub creator_id: PersonId, + pub post_id: PostId, + pub parent_id: Option, pub content: String, pub removed: Option, pub read: Option, @@ -69,9 +72,9 @@ pub struct CommentForm { #[table_name = "comment_like"] pub struct CommentLike { pub id: i32, - pub user_id: i32, - pub comment_id: i32, - pub post_id: i32, // TODO this is redundant + pub person_id: PersonId, + pub comment_id: CommentId, + pub post_id: PostId, // TODO this is redundant pub score: i16, pub published: chrono::NaiveDateTime, } @@ -79,9 +82,9 @@ pub struct CommentLike { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "comment_like"] pub struct CommentLikeForm { - pub user_id: i32, - pub comment_id: i32, - pub post_id: i32, // TODO this is redundant + pub person_id: PersonId, + pub comment_id: CommentId, + pub post_id: PostId, // TODO this is redundant pub score: i16, } @@ -90,14 +93,14 @@ pub struct CommentLikeForm { #[table_name = "comment_saved"] pub struct CommentSaved { pub id: i32, - pub comment_id: i32, - pub user_id: i32, + pub comment_id: CommentId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, } #[derive(Insertable, AsChangeset)] #[table_name = "comment_saved"] pub struct CommentSavedForm { - pub comment_id: i32, - pub user_id: i32, + pub comment_id: CommentId, + pub person_id: PersonId, } diff --git a/crates/db_schema/src/source/comment_report.rs b/crates/db_schema/src/source/comment_report.rs index ec53408d1..7b47bef20 100644 --- a/crates/db_schema/src/source/comment_report.rs +++ b/crates/db_schema/src/source/comment_report.rs @@ -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}; #[derive( @@ -8,12 +8,12 @@ use serde::{Deserialize, Serialize}; #[table_name = "comment_report"] pub struct CommentReport { pub id: i32, - pub creator_id: i32, - pub comment_id: i32, + pub creator_id: PersonId, + pub comment_id: CommentId, pub original_comment_text: String, pub reason: String, pub resolved: bool, - pub resolver_id: Option, + pub resolver_id: Option, pub published: chrono::NaiveDateTime, pub updated: Option, } @@ -21,8 +21,8 @@ pub struct CommentReport { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "comment_report"] pub struct CommentReportForm { - pub creator_id: i32, - pub comment_id: i32, + pub creator_id: PersonId, + pub comment_id: CommentId, pub original_comment_text: String, pub reason: String, } diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index b9fe12493..81789ecdf 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -1,17 +1,19 @@ use crate::{ - schema::{community, community_follower, community_moderator, community_user_ban}, + schema::{community, community_follower, community_moderator, community_person_ban}, + CommunityId, DbUrl, + PersonId, }; use serde::Serialize; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "community"] pub struct Community { - pub id: i32, + pub id: CommunityId, pub name: String, pub title: String, pub description: Option, - pub creator_id: i32, + pub creator_id: PersonId, pub removed: bool, pub published: chrono::NaiveDateTime, pub updated: Option, @@ -33,11 +35,11 @@ pub struct Community { #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "community"] pub struct CommunitySafe { - pub id: i32, + pub id: CommunityId, pub name: String, pub title: String, pub description: Option, - pub creator_id: i32, + pub creator_id: PersonId, pub removed: bool, pub published: chrono::NaiveDateTime, pub updated: Option, @@ -55,7 +57,7 @@ pub struct CommunityForm { pub name: String, pub title: String, pub description: Option, - pub creator_id: i32, + pub creator_id: PersonId, pub removed: Option, pub published: Option, pub updated: Option, @@ -78,33 +80,33 @@ pub struct CommunityForm { #[table_name = "community_moderator"] pub struct CommunityModerator { pub id: i32, - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, } #[derive(Insertable, AsChangeset, Clone)] #[table_name = "community_moderator"] pub struct CommunityModeratorForm { - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, } #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] #[belongs_to(Community)] -#[table_name = "community_user_ban"] -pub struct CommunityUserBan { +#[table_name = "community_person_ban"] +pub struct CommunityPersonBan { pub id: i32, - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, } #[derive(Insertable, AsChangeset, Clone)] -#[table_name = "community_user_ban"] -pub struct CommunityUserBanForm { - pub community_id: i32, - pub user_id: i32, +#[table_name = "community_person_ban"] +pub struct CommunityPersonBanForm { + pub community_id: CommunityId, + pub person_id: PersonId, } #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] @@ -112,8 +114,8 @@ pub struct CommunityUserBanForm { #[table_name = "community_follower"] pub struct CommunityFollower { pub id: i32, - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, pub pending: Option, } @@ -121,7 +123,7 @@ pub struct CommunityFollower { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "community_follower"] pub struct CommunityFollowerForm { - pub community_id: i32, - pub user_id: i32, + pub community_id: CommunityId, + pub person_id: PersonId, pub pending: bool, } diff --git a/crates/db_schema/src/source/local_user.rs b/crates/db_schema/src/source/local_user.rs new file mode 100644 index 000000000..750a2255c --- /dev/null +++ b/crates/db_schema/src/source/local_user.rs @@ -0,0 +1,56 @@ +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, + 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, +} + +// 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>, + pub admin: Option, + pub show_nsfw: Option, + pub theme: Option, + pub default_sort_type: Option, + pub default_listing_type: Option, + pub lang: Option, + pub show_avatars: Option, + pub send_notifications_to_email: Option, + pub matrix_user_id: Option>, +} + +/// 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, + 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, +} diff --git a/crates/db_schema/src/source/mod.rs b/crates/db_schema/src/source/mod.rs index a39dc1108..db928bd4f 100644 --- a/crates/db_schema/src/source/mod.rs +++ b/crates/db_schema/src/source/mod.rs @@ -2,11 +2,12 @@ pub mod activity; pub mod comment; pub mod comment_report; pub mod community; +pub mod local_user; pub mod moderator; pub mod password_reset_request; +pub mod person; +pub mod person_mention; pub mod post; pub mod post_report; pub mod private_message; pub mod site; -pub mod user; -pub mod user_mention; diff --git a/crates/db_schema/src/source/moderator.rs b/crates/db_schema/src/source/moderator.rs index d1a5d8308..19580fb92 100644 --- a/crates/db_schema/src/source/moderator.rs +++ b/crates/db_schema/src/source/moderator.rs @@ -1,13 +1,19 @@ -use crate::schema::{ - mod_add, - mod_add_community, - mod_ban, - mod_ban_from_community, - mod_lock_post, - mod_remove_comment, - mod_remove_community, - mod_remove_post, - mod_sticky_post, +use crate::{ + schema::{ + mod_add, + mod_add_community, + mod_ban, + mod_ban_from_community, + mod_lock_post, + mod_remove_comment, + mod_remove_community, + mod_remove_post, + mod_sticky_post, + }, + CommentId, + CommunityId, + PersonId, + PostId, }; use serde::Serialize; @@ -15,8 +21,8 @@ use serde::Serialize; #[table_name = "mod_remove_post"] pub struct ModRemovePost { pub id: i32, - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub reason: Option, pub removed: Option, pub when_: chrono::NaiveDateTime, @@ -25,8 +31,8 @@ pub struct ModRemovePost { #[derive(Insertable, AsChangeset)] #[table_name = "mod_remove_post"] pub struct ModRemovePostForm { - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub reason: Option, pub removed: Option, } @@ -35,8 +41,8 @@ pub struct ModRemovePostForm { #[table_name = "mod_lock_post"] pub struct ModLockPost { pub id: i32, - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub locked: Option, pub when_: chrono::NaiveDateTime, } @@ -44,8 +50,8 @@ pub struct ModLockPost { #[derive(Insertable, AsChangeset)] #[table_name = "mod_lock_post"] pub struct ModLockPostForm { - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub locked: Option, } @@ -53,8 +59,8 @@ pub struct ModLockPostForm { #[table_name = "mod_sticky_post"] pub struct ModStickyPost { pub id: i32, - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub stickied: Option, pub when_: chrono::NaiveDateTime, } @@ -62,8 +68,8 @@ pub struct ModStickyPost { #[derive(Insertable, AsChangeset)] #[table_name = "mod_sticky_post"] pub struct ModStickyPostForm { - pub mod_user_id: i32, - pub post_id: i32, + pub mod_person_id: PersonId, + pub post_id: PostId, pub stickied: Option, } @@ -71,8 +77,8 @@ pub struct ModStickyPostForm { #[table_name = "mod_remove_comment"] pub struct ModRemoveComment { pub id: i32, - pub mod_user_id: i32, - pub comment_id: i32, + pub mod_person_id: PersonId, + pub comment_id: CommentId, pub reason: Option, pub removed: Option, pub when_: chrono::NaiveDateTime, @@ -81,8 +87,8 @@ pub struct ModRemoveComment { #[derive(Insertable, AsChangeset)] #[table_name = "mod_remove_comment"] pub struct ModRemoveCommentForm { - pub mod_user_id: i32, - pub comment_id: i32, + pub mod_person_id: PersonId, + pub comment_id: CommentId, pub reason: Option, pub removed: Option, } @@ -91,8 +97,8 @@ pub struct ModRemoveCommentForm { #[table_name = "mod_remove_community"] pub struct ModRemoveCommunity { pub id: i32, - pub mod_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub community_id: CommunityId, pub reason: Option, pub removed: Option, pub expires: Option, @@ -102,8 +108,8 @@ pub struct ModRemoveCommunity { #[derive(Insertable, AsChangeset)] #[table_name = "mod_remove_community"] pub struct ModRemoveCommunityForm { - pub mod_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub community_id: CommunityId, pub reason: Option, pub removed: Option, pub expires: Option, @@ -113,9 +119,9 @@ pub struct ModRemoveCommunityForm { #[table_name = "mod_ban_from_community"] pub struct ModBanFromCommunity { pub id: i32, - pub mod_user_id: i32, - pub other_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, pub reason: Option, pub banned: Option, pub expires: Option, @@ -125,9 +131,9 @@ pub struct ModBanFromCommunity { #[derive(Insertable, AsChangeset)] #[table_name = "mod_ban_from_community"] pub struct ModBanFromCommunityForm { - pub mod_user_id: i32, - pub other_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, pub reason: Option, pub banned: Option, pub expires: Option, @@ -137,8 +143,8 @@ pub struct ModBanFromCommunityForm { #[table_name = "mod_ban"] pub struct ModBan { pub id: i32, - pub mod_user_id: i32, - pub other_user_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, pub reason: Option, pub banned: Option, pub expires: Option, @@ -148,8 +154,8 @@ pub struct ModBan { #[derive(Insertable, AsChangeset)] #[table_name = "mod_ban"] pub struct ModBanForm { - pub mod_user_id: i32, - pub other_user_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, pub reason: Option, pub banned: Option, pub expires: Option, @@ -159,9 +165,9 @@ pub struct ModBanForm { #[table_name = "mod_add_community"] pub struct ModAddCommunity { pub id: i32, - pub mod_user_id: i32, - pub other_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, pub removed: Option, pub when_: chrono::NaiveDateTime, } @@ -169,9 +175,9 @@ pub struct ModAddCommunity { #[derive(Insertable, AsChangeset)] #[table_name = "mod_add_community"] pub struct ModAddCommunityForm { - pub mod_user_id: i32, - pub other_user_id: i32, - pub community_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, pub removed: Option, } @@ -179,8 +185,8 @@ pub struct ModAddCommunityForm { #[table_name = "mod_add"] pub struct ModAdd { pub id: i32, - pub mod_user_id: i32, - pub other_user_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, pub removed: Option, pub when_: chrono::NaiveDateTime, } @@ -188,7 +194,7 @@ pub struct ModAdd { #[derive(Insertable, AsChangeset)] #[table_name = "mod_add"] pub struct ModAddForm { - pub mod_user_id: i32, - pub other_user_id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, pub removed: Option, } diff --git a/crates/db_schema/src/source/password_reset_request.rs b/crates/db_schema/src/source/password_reset_request.rs index f81f28efe..0af2d024d 100644 --- a/crates/db_schema/src/source/password_reset_request.rs +++ b/crates/db_schema/src/source/password_reset_request.rs @@ -1,17 +1,17 @@ -use crate::schema::password_reset_request; +use crate::{schema::password_reset_request, LocalUserId}; #[derive(Queryable, Identifiable, PartialEq, Debug)] #[table_name = "password_reset_request"] pub struct PasswordResetRequest { pub id: i32, - pub user_id: i32, pub token_encrypted: String, pub published: chrono::NaiveDateTime, + pub local_user_id: LocalUserId, } #[derive(Insertable, AsChangeset)] #[table_name = "password_reset_request"] pub struct PasswordResetRequestForm { - pub user_id: i32, + pub local_user_id: LocalUserId, pub token_encrypted: String, } diff --git a/crates/db_schema/src/source/user.rs b/crates/db_schema/src/source/person.rs similarity index 53% rename from crates/db_schema/src/source/user.rs rename to crates/db_schema/src/source/person.rs index f04b9a609..f669f0c55 100644 --- a/crates/db_schema/src/source/user.rs +++ b/crates/db_schema/src/source/person.rs @@ -1,30 +1,20 @@ use crate::{ - schema::{user_, user_alias_1, user_alias_2}, + schema::{person, person_alias_1, person_alias_2}, DbUrl, + PersonId, }; use serde::Serialize; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_"] -pub struct User_ { - pub id: i32, +#[table_name = "person"] +pub struct Person { + pub id: PersonId, pub name: String, pub preferred_username: Option, - pub password_encrypted: String, - pub email: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - 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, pub actor_id: DbUrl, pub bio: Option, pub local: bool, @@ -37,19 +27,17 @@ pub struct User_ { pub shared_inbox_url: Option, } -/// A safe representation of user, without the sensitive info +/// A safe representation of person, without the sensitive info #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_"] -pub struct UserSafe { - pub id: i32, +#[table_name = "person"] +pub struct PersonSafe { + pub id: PersonId, pub name: String, pub preferred_username: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - pub matrix_user_id: Option, pub actor_id: DbUrl, pub bio: Option, pub local: bool, @@ -59,56 +47,16 @@ pub struct UserSafe { pub shared_inbox_url: Option, } -/// A safe user view with only settings #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_"] -pub struct UserSafeSettings { - pub id: i32, +#[table_name = "person_alias_1"] +pub struct PersonAlias1 { + pub id: PersonId, pub name: String, pub preferred_username: Option, - pub email: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - 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, - pub actor_id: DbUrl, - pub bio: Option, - pub local: bool, - pub last_refreshed_at: chrono::NaiveDateTime, - pub banner: Option, - pub deleted: bool, -} - -#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_alias_1"] -pub struct UserAlias1 { - pub id: i32, - pub name: String, - pub preferred_username: Option, - pub password_encrypted: String, - pub email: Option, - pub avatar: Option, - pub admin: bool, - pub banned: bool, - pub published: chrono::NaiveDateTime, - pub updated: Option, - 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, pub actor_id: DbUrl, pub bio: Option, pub local: bool, @@ -117,48 +65,39 @@ pub struct UserAlias1 { pub last_refreshed_at: chrono::NaiveDateTime, pub banner: Option, pub deleted: bool, + pub inbox_url: DbUrl, + pub shared_inbox_url: Option, } #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_alias_1"] -pub struct UserSafeAlias1 { - pub id: i32, +#[table_name = "person_alias_1"] +pub struct PersonSafeAlias1 { + pub id: PersonId, pub name: String, pub preferred_username: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - pub matrix_user_id: Option, pub actor_id: DbUrl, pub bio: Option, pub local: bool, pub banner: Option, pub deleted: bool, + pub inbox_url: DbUrl, + pub shared_inbox_url: Option, } #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_alias_2"] -pub struct UserAlias2 { - pub id: i32, +#[table_name = "person_alias_2"] +pub struct PersonAlias2 { + pub id: PersonId, pub name: String, pub preferred_username: Option, - pub password_encrypted: String, - pub email: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - 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, pub actor_id: DbUrl, pub bio: Option, pub local: bool, @@ -167,54 +106,46 @@ pub struct UserAlias2 { pub last_refreshed_at: chrono::NaiveDateTime, pub banner: Option, pub deleted: bool, + pub inbox_url: DbUrl, + pub shared_inbox_url: Option, } #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] -#[table_name = "user_alias_2"] -pub struct UserSafeAlias2 { - pub id: i32, +#[table_name = "person_alias_1"] +pub struct PersonSafeAlias2 { + pub id: PersonId, pub name: String, pub preferred_username: Option, pub avatar: Option, - pub admin: bool, pub banned: bool, pub published: chrono::NaiveDateTime, pub updated: Option, - pub matrix_user_id: Option, pub actor_id: DbUrl, pub bio: Option, pub local: bool, pub banner: Option, pub deleted: bool, + pub inbox_url: DbUrl, + pub shared_inbox_url: Option, } #[derive(Insertable, AsChangeset, Clone)] -#[table_name = "user_"] -pub struct UserForm { +#[table_name = "person"] +pub struct PersonForm { pub name: String, pub preferred_username: Option>, - pub password_encrypted: String, - pub admin: bool, - pub banned: Option, - pub email: Option>, pub avatar: Option>, + pub banned: Option, pub published: Option, pub updated: Option, - 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>, pub actor_id: Option, pub bio: Option>, - pub local: bool, - pub private_key: Option, - pub public_key: Option, + pub local: Option, + pub private_key: Option>, + pub public_key: Option>, pub last_refreshed_at: Option, pub banner: Option>, + pub deleted: Option, pub inbox_url: Option, pub shared_inbox_url: Option>, } diff --git a/crates/db_schema/src/source/person_mention.rs b/crates/db_schema/src/source/person_mention.rs new file mode 100644 index 000000000..61ed32b0b --- /dev/null +++ b/crates/db_schema/src/source/person_mention.rs @@ -0,0 +1,27 @@ +use crate::{ + schema::person_mention, + source::comment::Comment, + CommentId, + PersonId, + PersonMentionId, +}; +use serde::Serialize; + +#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)] +#[belongs_to(Comment)] +#[table_name = "person_mention"] +pub struct PersonMention { + pub id: PersonMentionId, + pub recipient_id: PersonId, + pub comment_id: CommentId, + pub read: bool, + pub published: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset)] +#[table_name = "person_mention"] +pub struct PersonMentionForm { + pub recipient_id: PersonId, + pub comment_id: CommentId, + pub read: Option, +} diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index c8cc51cd0..34b889d46 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -1,18 +1,21 @@ use crate::{ schema::{post, post_like, post_read, post_saved}, + CommunityId, DbUrl, + PersonId, + PostId, }; use serde::Serialize; #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "post"] pub struct Post { - pub id: i32, + pub id: PostId, pub name: String, pub url: Option, pub body: Option, - pub creator_id: i32, - pub community_id: i32, + pub creator_id: PersonId, + pub community_id: CommunityId, pub removed: bool, pub locked: bool, pub published: chrono::NaiveDateTime, @@ -34,8 +37,8 @@ pub struct PostForm { pub name: String, pub url: Option, pub body: Option, - pub creator_id: i32, - pub community_id: i32, + pub creator_id: PersonId, + pub community_id: CommunityId, pub removed: Option, pub locked: Option, pub published: Option, @@ -56,8 +59,8 @@ pub struct PostForm { #[table_name = "post_like"] pub struct PostLike { pub id: i32, - pub post_id: i32, - pub user_id: i32, + pub post_id: PostId, + pub person_id: PersonId, pub score: i16, pub published: chrono::NaiveDateTime, } @@ -65,8 +68,8 @@ pub struct PostLike { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "post_like"] pub struct PostLikeForm { - pub post_id: i32, - pub user_id: i32, + pub post_id: PostId, + pub person_id: PersonId, pub score: i16, } @@ -75,16 +78,16 @@ pub struct PostLikeForm { #[table_name = "post_saved"] pub struct PostSaved { pub id: i32, - pub post_id: i32, - pub user_id: i32, + pub post_id: PostId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, } #[derive(Insertable, AsChangeset)] #[table_name = "post_saved"] pub struct PostSavedForm { - pub post_id: i32, - pub user_id: i32, + pub post_id: PostId, + pub person_id: PersonId, } #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] @@ -92,18 +95,14 @@ pub struct PostSavedForm { #[table_name = "post_read"] pub struct PostRead { pub id: i32, - - pub post_id: i32, - - pub user_id: i32, - + pub post_id: PostId, + pub person_id: PersonId, pub published: chrono::NaiveDateTime, } #[derive(Insertable, AsChangeset)] #[table_name = "post_read"] pub struct PostReadForm { - pub post_id: i32, - - pub user_id: i32, + pub post_id: PostId, + pub person_id: PersonId, } diff --git a/crates/db_schema/src/source/post_report.rs b/crates/db_schema/src/source/post_report.rs index 62ef31cd8..d32d7e1e4 100644 --- a/crates/db_schema/src/source/post_report.rs +++ b/crates/db_schema/src/source/post_report.rs @@ -1,4 +1,4 @@ -use crate::{schema::post_report, source::post::Post, DbUrl}; +use crate::{schema::post_report, source::post::Post, DbUrl, PersonId, PostId}; use serde::{Deserialize, Serialize}; #[derive( @@ -8,14 +8,14 @@ use serde::{Deserialize, Serialize}; #[table_name = "post_report"] pub struct PostReport { pub id: i32, - pub creator_id: i32, - pub post_id: i32, + pub creator_id: PersonId, + pub post_id: PostId, pub original_post_name: String, pub original_post_url: Option, pub original_post_body: Option, pub reason: String, pub resolved: bool, - pub resolver_id: Option, + pub resolver_id: Option, pub published: chrono::NaiveDateTime, pub updated: Option, } @@ -23,8 +23,8 @@ pub struct PostReport { #[derive(Insertable, AsChangeset, Clone)] #[table_name = "post_report"] pub struct PostReportForm { - pub creator_id: i32, - pub post_id: i32, + pub creator_id: PersonId, + pub post_id: PostId, pub original_post_name: String, pub original_post_url: Option, pub original_post_body: Option, diff --git a/crates/db_schema/src/source/private_message.rs b/crates/db_schema/src/source/private_message.rs index 949c97709..6d46c0129 100644 --- a/crates/db_schema/src/source/private_message.rs +++ b/crates/db_schema/src/source/private_message.rs @@ -1,12 +1,12 @@ -use crate::{schema::private_message, DbUrl}; +use crate::{schema::private_message, DbUrl, PersonId, PrivateMessageId}; use serde::Serialize; #[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "private_message"] pub struct PrivateMessage { - pub id: i32, - pub creator_id: i32, - pub recipient_id: i32, + pub id: PrivateMessageId, + pub creator_id: PersonId, + pub recipient_id: PersonId, pub content: String, pub deleted: bool, pub read: bool, @@ -19,8 +19,8 @@ pub struct PrivateMessage { #[derive(Insertable, AsChangeset)] #[table_name = "private_message"] pub struct PrivateMessageForm { - pub creator_id: i32, - pub recipient_id: i32, + pub creator_id: PersonId, + pub recipient_id: PersonId, pub content: String, pub deleted: Option, pub read: Option, diff --git a/crates/db_schema/src/source/site.rs b/crates/db_schema/src/source/site.rs index 998e9f9d1..0723772eb 100644 --- a/crates/db_schema/src/source/site.rs +++ b/crates/db_schema/src/source/site.rs @@ -1,4 +1,4 @@ -use crate::{schema::site, DbUrl}; +use crate::{schema::site, DbUrl, PersonId}; use serde::Serialize; #[derive(Queryable, Identifiable, PartialEq, Debug, Clone, Serialize)] @@ -7,7 +7,7 @@ pub struct Site { pub id: i32, pub name: String, pub description: Option, - pub creator_id: i32, + pub creator_id: PersonId, pub published: chrono::NaiveDateTime, pub updated: Option, pub enable_downvotes: bool, @@ -22,7 +22,7 @@ pub struct Site { pub struct SiteForm { pub name: String, pub description: Option, - pub creator_id: i32, + pub creator_id: PersonId, pub updated: Option, pub enable_downvotes: bool, pub open_registration: bool, diff --git a/crates/db_schema/src/source/user_mention.rs b/crates/db_schema/src/source/user_mention.rs deleted file mode 100644 index 64fd56006..000000000 --- a/crates/db_schema/src/source/user_mention.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::{schema::user_mention, source::comment::Comment}; -use serde::Serialize; - -#[derive(Clone, Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)] -#[belongs_to(Comment)] -#[table_name = "user_mention"] -pub struct UserMention { - pub id: i32, - pub recipient_id: i32, - pub comment_id: i32, - pub read: bool, - pub published: chrono::NaiveDateTime, -} - -#[derive(Insertable, AsChangeset)] -#[table_name = "user_mention"] -pub struct UserMentionForm { - pub recipient_id: i32, - pub comment_id: i32, - pub read: Option, -} diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 2863f6259..2aa4bdfcf 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -1,14 +1,15 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{comment, comment_report, community, post, user_, user_alias_1, user_alias_2}, + schema::{comment, comment_report, community, person, person_alias_1, person_alias_2, post}, source::{ comment::Comment, comment_report::CommentReport, community::{Community, CommunitySafe}, + person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2}, post::Post, - user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_}, }, + CommunityId, }; use serde::Serialize; @@ -18,9 +19,9 @@ pub struct CommentReportView { pub comment: Comment, pub post: Post, pub community: CommunitySafe, - pub creator: UserSafe, - pub comment_creator: UserSafeAlias1, - pub resolver: Option, + pub creator: PersonSafe, + pub comment_creator: PersonSafeAlias1, + pub resolver: Option, } type CommentReportViewTuple = ( @@ -28,9 +29,9 @@ type CommentReportViewTuple = ( Comment, Post, CommunitySafe, - UserSafe, - UserSafeAlias1, - Option, + PersonSafe, + PersonSafeAlias1, + Option, ); impl CommentReportView { @@ -44,19 +45,19 @@ impl CommentReportView { .inner_join(comment::table) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_::table.on(comment_report::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) + .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) .left_join( - user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())), + person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())), ) .select(( comment_report::all_columns, comment::all_columns, post::all_columns, Community::safe_columns_tuple(), - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), - UserAlias2::safe_columns_tuple().nullable(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + PersonAlias2::safe_columns_tuple().nullable(), )) .first::(conn)?; @@ -75,8 +76,11 @@ impl CommentReportView { /// /// * `community_ids` - a Vec of community_ids to get a count for /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator - /// for a user id - pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result { + /// for a person id + pub fn get_report_count( + conn: &PgConnection, + community_ids: &[CommunityId], + ) -> Result { use diesel::dsl::*; comment_report::table .inner_join(comment::table) @@ -93,7 +97,7 @@ impl CommentReportView { pub struct CommentReportQueryBuilder<'a> { conn: &'a PgConnection, - community_ids: Option>, // TODO bad way to do this + community_ids: Option>, // TODO bad way to do this page: Option, limit: Option, resolved: Option, @@ -110,7 +114,7 @@ impl<'a> CommentReportQueryBuilder<'a> { } } - pub fn community_ids>>(mut self, community_ids: T) -> Self { + pub fn community_ids>>(mut self, community_ids: T) -> Self { self.community_ids = community_ids.get_optional(); self } @@ -135,19 +139,19 @@ impl<'a> CommentReportQueryBuilder<'a> { .inner_join(comment::table) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_::table.on(comment_report::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) + .inner_join(person::table.on(comment_report::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) .left_join( - user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())), + person_alias_2::table.on(comment_report::resolver_id.eq(person_alias_2::id.nullable())), ) .select(( comment_report::all_columns, comment::all_columns, post::all_columns, Community::safe_columns_tuple(), - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), - UserAlias2::safe_columns_tuple().nullable(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + PersonAlias2::safe_columns_tuple().nullable(), )) .into_boxed(); diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 56b22a7f0..6c5850ad3 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -19,29 +19,33 @@ use lemmy_db_schema::{ comment_saved, community, community_follower, - community_user_ban, + community_person_ban, + person, + person_alias_1, post, - user_, - user_alias_1, }, source::{ comment::{Comment, CommentAlias1, CommentSaved}, - community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, + community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, post::Post, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, }, + CommentId, + CommunityId, + PersonId, + PostId, }; use serde::Serialize; #[derive(Debug, PartialEq, Serialize, Clone)] pub struct CommentView { pub comment: Comment, - pub creator: UserSafe, - pub recipient: Option, // Left joins to comment and user + pub creator: PersonSafe, + pub recipient: Option, // Left joins to comment and person pub post: Post, pub community: CommunitySafe, pub counts: CommentAggregates, - pub creator_banned_from_community: bool, // Left Join to CommunityUserBan + pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan pub subscribed: bool, // Left join to CommunityFollower pub saved: bool, // Left join to CommentSaved pub my_vote: Option, // Left join to CommentLike @@ -49,13 +53,13 @@ pub struct CommentView { type CommentViewTuple = ( Comment, - UserSafe, + PersonSafe, Option, - Option, + Option, Post, CommunitySafe, CommentAggregates, - Option, + Option, Option, Option, Option, @@ -64,11 +68,11 @@ type CommentViewTuple = ( impl CommentView { pub fn read( conn: &PgConnection, - comment_id: i32, - my_user_id: Option, + comment_id: CommentId, + my_person_id: Option, ) -> Result { // The left join below will return None in this case - let user_id_join = my_user_id.unwrap_or(-1); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let ( comment, @@ -84,59 +88,59 @@ impl CommentView { comment_like, ) = comment::table .find(comment_id) - .inner_join(user_::table) + .inner_join(person::table) // recipient here .left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id))) - .left_join(user_alias_1::table.on(user_alias_1::id.eq(comment_alias_1::creator_id))) + .left_join(person_alias_1::table.on(person_alias_1::id.eq(comment_alias_1::creator_id))) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(comment_aggregates::table) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( community::id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(comment::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(comment::creator_id)), ), ) .left_join( community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( comment_saved::table.on( comment::id .eq(comment_saved::comment_id) - .and(comment_saved::user_id.eq(user_id_join)), + .and(comment_saved::person_id.eq(person_id_join)), ), ) .left_join( comment_like::table.on( comment::id .eq(comment_like::comment_id) - .and(comment_like::user_id.eq(user_id_join)), + .and(comment_like::person_id.eq(person_id_join)), ), ) .select(( comment::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), comment_alias_1::all_columns.nullable(), - UserAlias1::safe_columns_tuple().nullable(), + PersonAlias1::safe_columns_tuple().nullable(), post::all_columns, Community::safe_columns_tuple(), comment_aggregates::all_columns, - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), community_follower::all_columns.nullable(), comment_saved::all_columns.nullable(), comment_like::score.nullable(), )) .first::(conn)?; - // If a user is given, then my_vote, if None, should be 0, not null - // Necessary to differentiate between other user's votes - let my_vote = if my_user_id.is_some() && comment_like.is_none() { + // If a person is given, then my_vote, if None, should be 0, not null + // Necessary to differentiate between other person's votes + let my_vote = if my_person_id.is_some() && comment_like.is_none() { Some(0) } else { comment_like @@ -156,9 +160,9 @@ impl CommentView { }) } - /// Gets the recipient user id. + /// Gets the recipient person id. /// If there is no parent comment, its the post creator - pub fn get_recipient_id(&self) -> i32 { + pub fn get_recipient_id(&self) -> PersonId { match &self.recipient { Some(parent_commenter) => parent_commenter.id, None => self.post.creator_id, @@ -170,12 +174,12 @@ pub struct CommentQueryBuilder<'a> { conn: &'a PgConnection, listing_type: ListingType, sort: &'a SortType, - community_id: Option, + community_id: Option, community_name: Option, - post_id: Option, - creator_id: Option, - recipient_id: Option, - my_user_id: Option, + post_id: Option, + creator_id: Option, + recipient_id: Option, + my_person_id: Option, search_term: Option, saved_only: bool, unread_only: bool, @@ -194,7 +198,7 @@ impl<'a> CommentQueryBuilder<'a> { post_id: None, creator_id: None, recipient_id: None, - my_user_id: None, + my_person_id: None, search_term: None, saved_only: false, unread_only: false, @@ -213,28 +217,28 @@ impl<'a> CommentQueryBuilder<'a> { self } - pub fn post_id>(mut self, post_id: T) -> Self { + pub fn post_id>(mut self, post_id: T) -> Self { self.post_id = post_id.get_optional(); self } - pub fn creator_id>(mut self, creator_id: T) -> Self { + pub fn creator_id>(mut self, creator_id: T) -> Self { self.creator_id = creator_id.get_optional(); self } - pub fn recipient_id>(mut self, recipient_id: T) -> Self { + pub fn recipient_id>(mut self, recipient_id: T) -> Self { self.recipient_id = recipient_id.get_optional(); self } - pub fn community_id>(mut self, community_id: T) -> Self { + pub fn community_id>(mut self, community_id: T) -> Self { self.community_id = community_id.get_optional(); self } - pub fn my_user_id>(mut self, my_user_id: T) -> Self { - self.my_user_id = my_user_id.get_optional(); + pub fn my_person_id>(mut self, my_person_id: T) -> Self { + self.my_person_id = my_person_id.get_optional(); self } @@ -272,53 +276,53 @@ impl<'a> CommentQueryBuilder<'a> { use diesel::dsl::*; // The left join below will return None in this case - let user_id_join = self.my_user_id.unwrap_or(-1); + let person_id_join = self.my_person_id.unwrap_or(PersonId(-1)); let mut query = comment::table - .inner_join(user_::table) + .inner_join(person::table) // recipient here .left_join(comment_alias_1::table.on(comment_alias_1::id.nullable().eq(comment::parent_id))) - .left_join(user_alias_1::table.on(user_alias_1::id.eq(comment_alias_1::creator_id))) + .left_join(person_alias_1::table.on(person_alias_1::id.eq(comment_alias_1::creator_id))) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .inner_join(comment_aggregates::table) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( community::id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(comment::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(comment::creator_id)), ), ) .left_join( community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( comment_saved::table.on( comment::id .eq(comment_saved::comment_id) - .and(comment_saved::user_id.eq(user_id_join)), + .and(comment_saved::person_id.eq(person_id_join)), ), ) .left_join( comment_like::table.on( comment::id .eq(comment_like::comment_id) - .and(comment_like::user_id.eq(user_id_join)), + .and(comment_like::person_id.eq(person_id_join)), ), ) .select(( comment::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), comment_alias_1::all_columns.nullable(), - UserAlias1::safe_columns_tuple().nullable(), + PersonAlias1::safe_columns_tuple().nullable(), post::all_columns, Community::safe_columns_tuple(), comment_aggregates::all_columns, - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), community_follower::all_columns.nullable(), comment_saved::all_columns.nullable(), comment_like::score.nullable(), @@ -329,7 +333,7 @@ impl<'a> CommentQueryBuilder<'a> { if let Some(recipient_id) = self.recipient_id { query = query // TODO needs lots of testing - .filter(user_alias_1::id.eq(recipient_id)) // Gets the comment replies + .filter(person_alias_1::id.eq(recipient_id)) // Gets the comment replies .or_filter( comment::parent_id .is_null() @@ -367,7 +371,7 @@ impl<'a> CommentQueryBuilder<'a> { query = match self.listing_type { // ListingType::Subscribed => query.filter(community_follower::subscribed.eq(true)), - ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), + ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Local => query.filter(community::local.eq(true)), _ => query, }; @@ -439,10 +443,8 @@ mod tests { establish_unpooled_connection, Crud, Likeable, - ListingType, - SortType, }; - use lemmy_db_schema::source::{comment::*, community::*, post::*, user::*}; + use lemmy_db_schema::source::{comment::*, community::*, person::*, post::*}; use serial_test::serial; #[test] @@ -450,28 +452,18 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let new_user = UserForm { + let new_person = PersonForm { name: "timmy".into(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, - admin: false, - banned: Some(false), + banned: None, + deleted: None, 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -479,13 +471,13 @@ mod tests { 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 { name: "test community 5".to_string(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -507,7 +499,7 @@ mod tests { let new_post = PostForm { name: "A test post 2".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, url: None, body: None, community_id: inserted_community.id, @@ -530,7 +522,7 @@ mod tests { let comment_form = CommentForm { content: "A test comment 32".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, parent_id: None, removed: None, @@ -547,7 +539,7 @@ mod tests { let comment_like_form = CommentLikeForm { comment_id: inserted_comment.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -555,7 +547,7 @@ mod tests { let agg = CommentAggregates::read(&conn, inserted_comment.id).unwrap(); - let expected_comment_view_no_user = CommentView { + let expected_comment_view_no_person = CommentView { creator_banned_from_community: false, my_vote: None, subscribed: false, @@ -563,7 +555,7 @@ mod tests { comment: Comment { id: inserted_comment.id, content: "A test comment 32".into(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, post_id: inserted_post.id, parent_id: None, removed: false, @@ -574,29 +566,27 @@ mod tests { updated: None, local: true, }, - creator: UserSafe { - id: inserted_user.id, + creator: PersonSafe { + id: inserted_person.id, name: "timmy".into(), preferred_username: None, - published: inserted_user.published, + published: inserted_person.published, avatar: None, - actor_id: inserted_user.actor_id.to_owned(), + actor_id: inserted_person.actor_id.to_owned(), local: true, banned: false, deleted: false, bio: None, banner: None, - admin: false, updated: None, - matrix_user_id: None, - inbox_url: inserted_user.inbox_url.to_owned(), + inbox_url: inserted_person.inbox_url.to_owned(), shared_inbox_url: None, }, recipient: None, post: Post { id: inserted_post.id, name: inserted_post.name.to_owned(), - creator_id: inserted_user.id, + creator_id: inserted_person.id, url: None, body: None, published: inserted_post.published, @@ -625,7 +615,7 @@ mod tests { local: true, title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, updated: None, banner: None, published: inserted_community.published, @@ -640,30 +630,33 @@ mod tests { }, }; - let mut expected_comment_view_with_user = expected_comment_view_no_user.to_owned(); - expected_comment_view_with_user.my_vote = Some(1); + let mut expected_comment_view_with_person = expected_comment_view_no_person.to_owned(); + expected_comment_view_with_person.my_vote = Some(1); - let read_comment_views_no_user = CommentQueryBuilder::create(&conn) + let read_comment_views_no_person = CommentQueryBuilder::create(&conn) .post_id(inserted_post.id) .list() .unwrap(); - let read_comment_views_with_user = CommentQueryBuilder::create(&conn) + let read_comment_views_with_person = CommentQueryBuilder::create(&conn) .post_id(inserted_post.id) - .my_user_id(inserted_user.id) + .my_person_id(inserted_person.id) .list() .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 num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap(); Post::delete(&conn, inserted_post.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_view_no_user, read_comment_views_no_user[0]); assert_eq!( - expected_comment_view_with_user, - read_comment_views_with_user[0] + expected_comment_view_no_person, + read_comment_views_no_person[0] + ); + assert_eq!( + expected_comment_view_with_person, + read_comment_views_with_person[0] ); assert_eq!(1, num_deleted); assert_eq!(1, like_removed); diff --git a/crates/db_views/src/lib.rs b/crates/db_views/src/lib.rs index a9369ed24..54435c1e2 100644 --- a/crates/db_views/src/lib.rs +++ b/crates/db_views/src/lib.rs @@ -3,6 +3,7 @@ extern crate serial_test; pub mod comment_report_view; pub mod comment_view; +pub mod local_user_view; pub mod post_report_view; pub mod post_view; pub mod private_message_view; diff --git a/crates/db_views/src/local_user_view.rs b/crates/db_views/src/local_user_view.rs new file mode 100644 index 000000000..85a83e156 --- /dev/null +++ b/crates/db_views/src/local_user_view.rs @@ -0,0 +1,147 @@ +use diesel::{result::Error, *}; +use lemmy_db_queries::{aggregates::person_aggregates::PersonAggregates, ToSafe, ToSafeSettings}; +use lemmy_db_schema::{ + schema::{local_user, person, person_aggregates}, + source::{ + local_user::{LocalUser, LocalUserSettings}, + person::{Person, PersonSafe}, + }, + LocalUserId, + PersonId, +}; +use serde::Serialize; + +#[derive(Debug, Serialize, Clone)] +pub struct LocalUserView { + pub local_user: LocalUser, + pub person: Person, + pub counts: PersonAggregates, +} + +type LocalUserViewTuple = (LocalUser, Person, PersonAggregates); + +impl LocalUserView { + pub fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result { + let (local_user, person, counts) = local_user::table + .find(local_user_id) + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .select(( + local_user::all_columns, + person::all_columns, + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + local_user, + person, + counts, + }) + } + + pub fn read_person(conn: &PgConnection, person_id: PersonId) -> Result { + let (local_user, person, counts) = local_user::table + .filter(person::id.eq(person_id)) + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .select(( + local_user::all_columns, + person::all_columns, + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + local_user, + person, + counts, + }) + } + + // TODO check where this is used + pub fn read_from_name(conn: &PgConnection, name: &str) -> Result { + let (local_user, person, counts) = local_user::table + .filter(person::name.eq(name)) + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .select(( + local_user::all_columns, + person::all_columns, + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + person, + counts, + local_user, + }) + } + + pub fn find_by_email_or_name(conn: &PgConnection, name_or_email: &str) -> Result { + let (local_user, person, counts) = local_user::table + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .filter( + person::name + .ilike(name_or_email) + .or(local_user::email.ilike(name_or_email)), + ) + .select(( + local_user::all_columns, + person::all_columns, + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + person, + counts, + local_user, + }) + } + + pub fn find_by_email(conn: &PgConnection, from_email: &str) -> Result { + let (local_user, person, counts) = local_user::table + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .filter(local_user::email.eq(from_email)) + .select(( + local_user::all_columns, + person::all_columns, + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + person, + counts, + local_user, + }) + } +} + +#[derive(Debug, Serialize, Clone)] +pub struct LocalUserSettingsView { + pub local_user: LocalUserSettings, + pub person: PersonSafe, + pub counts: PersonAggregates, +} + +type LocalUserSettingsViewTuple = (LocalUserSettings, PersonSafe, PersonAggregates); + +impl LocalUserSettingsView { + pub fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result { + let (local_user, person, counts) = local_user::table + .find(local_user_id) + .inner_join(person::table) + .inner_join(person_aggregates::table.on(person::id.eq(person_aggregates::person_id))) + .select(( + LocalUser::safe_settings_columns_tuple(), + Person::safe_columns_tuple(), + person_aggregates::all_columns, + )) + .first::(conn)?; + Ok(Self { + person, + counts, + local_user, + }) + } +} diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index 741162e3e..a3dc49e28 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -1,13 +1,14 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, post, post_report, user_, user_alias_1, user_alias_2}, + schema::{community, person, person_alias_1, person_alias_2, post, post_report}, source::{ community::{Community, CommunitySafe}, + person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2}, post::Post, post_report::PostReport, - user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_}, }, + CommunityId, }; use serde::Serialize; @@ -16,18 +17,18 @@ pub struct PostReportView { pub post_report: PostReport, pub post: Post, pub community: CommunitySafe, - pub creator: UserSafe, - pub post_creator: UserSafeAlias1, - pub resolver: Option, + pub creator: PersonSafe, + pub post_creator: PersonSafeAlias1, + pub resolver: Option, } type PostReportViewTuple = ( PostReport, Post, CommunitySafe, - UserSafe, - UserSafeAlias1, - Option, + PersonSafe, + PersonSafeAlias1, + Option, ); impl PostReportView { @@ -39,16 +40,18 @@ impl PostReportView { .find(report_id) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_::table.on(post_report::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) - .left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable()))) + .inner_join(person::table.on(post_report::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) + .left_join( + person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())), + ) .select(( post_report::all_columns, post::all_columns, Community::safe_columns_tuple(), - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), - UserAlias2::safe_columns_tuple().nullable(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + PersonAlias2::safe_columns_tuple().nullable(), )) .first::(conn)?; @@ -66,8 +69,11 @@ impl PostReportView { /// /// * `community_ids` - a Vec of community_ids to get a count for /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator - /// for a user id - pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result { + /// for a person id + pub fn get_report_count( + conn: &PgConnection, + community_ids: &[CommunityId], + ) -> Result { use diesel::dsl::*; post_report::table .inner_join(post::table) @@ -83,7 +89,7 @@ impl PostReportView { pub struct PostReportQueryBuilder<'a> { conn: &'a PgConnection, - community_ids: Option>, // TODO bad way to do this + community_ids: Option>, // TODO bad way to do this page: Option, limit: Option, resolved: Option, @@ -100,7 +106,7 @@ impl<'a> PostReportQueryBuilder<'a> { } } - pub fn community_ids>>(mut self, community_ids: T) -> Self { + pub fn community_ids>>(mut self, community_ids: T) -> Self { self.community_ids = community_ids.get_optional(); self } @@ -124,16 +130,18 @@ impl<'a> PostReportQueryBuilder<'a> { let mut query = post_report::table .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_::table.on(post_report::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id))) - .left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable()))) + .inner_join(person::table.on(post_report::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id))) + .left_join( + person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())), + ) .select(( post_report::all_columns, post::all_columns, Community::safe_columns_tuple(), - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), - UserAlias2::safe_columns_tuple().nullable(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + PersonAlias2::safe_columns_tuple().nullable(), )) .into_boxed(); diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index e7b488275..fe852e376 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -14,19 +14,22 @@ use lemmy_db_schema::{ schema::{ community, community_follower, - community_user_ban, + community_person_ban, + person, post, post_aggregates, post_like, post_read, post_saved, - user_, }, source::{ - community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, + community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe}, + person::{Person, PersonSafe}, post::{Post, PostRead, PostSaved}, - user::{UserSafe, User_}, }, + CommunityId, + PersonId, + PostId, }; use log::debug; use serde::Serialize; @@ -34,9 +37,9 @@ use serde::Serialize; #[derive(Debug, PartialEq, Serialize, Clone)] pub struct PostView { pub post: Post, - pub creator: UserSafe, + pub creator: PersonSafe, pub community: CommunitySafe, - pub creator_banned_from_community: bool, // Left Join to CommunityUserBan + pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan pub counts: PostAggregates, pub subscribed: bool, // Left join to CommunityFollower pub saved: bool, // Left join to PostSaved @@ -46,9 +49,9 @@ pub struct PostView { type PostViewTuple = ( Post, - UserSafe, + PersonSafe, CommunitySafe, - Option, + Option, PostAggregates, Option, Option, @@ -57,9 +60,13 @@ type PostViewTuple = ( ); impl PostView { - pub fn read(conn: &PgConnection, post_id: i32, my_user_id: Option) -> Result { + pub fn read( + conn: &PgConnection, + post_id: PostId, + my_person_id: Option, + ) -> Result { // The left join below will return None in this case - let user_id_join = my_user_id.unwrap_or(-1); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let ( post, @@ -73,13 +80,13 @@ impl PostView { post_like, ) = post::table .find(post_id) - .inner_join(user_::table) + .inner_join(person::table) .inner_join(community::table) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( post::community_id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(post::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(post::creator_id)), ), ) .inner_join(post_aggregates::table) @@ -87,35 +94,35 @@ impl PostView { community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( post_saved::table.on( post::id .eq(post_saved::post_id) - .and(post_saved::user_id.eq(user_id_join)), + .and(post_saved::person_id.eq(person_id_join)), ), ) .left_join( post_read::table.on( post::id .eq(post_read::post_id) - .and(post_read::user_id.eq(user_id_join)), + .and(post_read::person_id.eq(person_id_join)), ), ) .left_join( post_like::table.on( post::id .eq(post_like::post_id) - .and(post_like::user_id.eq(user_id_join)), + .and(post_like::person_id.eq(person_id_join)), ), ) .select(( post::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), Community::safe_columns_tuple(), - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), post_aggregates::all_columns, community_follower::all_columns.nullable(), post_saved::all_columns.nullable(), @@ -124,9 +131,9 @@ impl PostView { )) .first::(conn)?; - // If a user is given, then my_vote, if None, should be 0, not null - // Necessary to differentiate between other user's votes - let my_vote = if my_user_id.is_some() && post_like.is_none() { + // If a person is given, then my_vote, if None, should be 0, not null + // Necessary to differentiate between other person's votes + let my_vote = if my_person_id.is_some() && post_like.is_none() { Some(0) } else { post_like @@ -150,10 +157,10 @@ pub struct PostQueryBuilder<'a> { conn: &'a PgConnection, listing_type: &'a ListingType, sort: &'a SortType, - creator_id: Option, - community_id: Option, + creator_id: Option, + community_id: Option, community_name: Option, - my_user_id: Option, + my_person_id: Option, search_term: Option, url_search: Option, show_nsfw: bool, @@ -172,7 +179,7 @@ impl<'a> PostQueryBuilder<'a> { creator_id: None, community_id: None, community_name: None, - my_user_id: None, + my_person_id: None, search_term: None, url_search: None, show_nsfw: true, @@ -193,13 +200,13 @@ impl<'a> PostQueryBuilder<'a> { self } - pub fn community_id>(mut self, community_id: T) -> Self { + pub fn community_id>(mut self, community_id: T) -> Self { self.community_id = community_id.get_optional(); self } - pub fn my_user_id>(mut self, my_user_id: T) -> Self { - self.my_user_id = my_user_id.get_optional(); + pub fn my_person_id>(mut self, my_person_id: T) -> Self { + self.my_person_id = my_person_id.get_optional(); self } @@ -208,7 +215,7 @@ impl<'a> PostQueryBuilder<'a> { self } - pub fn creator_id>(mut self, creator_id: T) -> Self { + pub fn creator_id>(mut self, creator_id: T) -> Self { self.creator_id = creator_id.get_optional(); self } @@ -247,16 +254,16 @@ impl<'a> PostQueryBuilder<'a> { use diesel::dsl::*; // The left join below will return None in this case - let user_id_join = self.my_user_id.unwrap_or(-1); + let person_id_join = self.my_person_id.unwrap_or(PersonId(-1)); let mut query = post::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(community::table) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( post::community_id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(community::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(community::creator_id)), ), ) .inner_join(post_aggregates::table) @@ -264,35 +271,35 @@ impl<'a> PostQueryBuilder<'a> { community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( post_saved::table.on( post::id .eq(post_saved::post_id) - .and(post_saved::user_id.eq(user_id_join)), + .and(post_saved::person_id.eq(person_id_join)), ), ) .left_join( post_read::table.on( post::id .eq(post_read::post_id) - .and(post_read::user_id.eq(user_id_join)), + .and(post_read::person_id.eq(person_id_join)), ), ) .left_join( post_like::table.on( post::id .eq(post_like::post_id) - .and(post_like::user_id.eq(user_id_join)), + .and(post_like::person_id.eq(person_id_join)), ), ) .select(( post::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), Community::safe_columns_tuple(), - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), post_aggregates::all_columns, community_follower::all_columns.nullable(), post_saved::all_columns.nullable(), @@ -302,7 +309,7 @@ impl<'a> PostQueryBuilder<'a> { .into_boxed(); query = match self.listing_type { - ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), + ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Local => query.filter(community::local.eq(true)), _ => query, }; @@ -333,7 +340,7 @@ impl<'a> PostQueryBuilder<'a> { ); } - // If its for a specific user, show the removed / deleted + // If its for a specific person, show the removed / deleted if let Some(creator_id) = self.creator_id { query = query.filter(post::creator_id.eq(creator_id)); } @@ -433,7 +440,7 @@ mod tests { ListingType, SortType, }; - use lemmy_db_schema::source::{community::*, post::*, user::*}; + use lemmy_db_schema::source::{community::*, person::*, post::*}; use serial_test::serial; #[test] @@ -441,32 +448,22 @@ mod tests { fn test_crud() { let conn = establish_unpooled_connection(); - let user_name = "tegan".to_string(); + let person_name = "tegan".to_string(); let community_name = "test_community_3".to_string(); let post_name = "test post 3".to_string(); - let new_user = UserForm { - name: user_name.to_owned(), + let new_person = PersonForm { + name: person_name.to_owned(), preferred_username: None, - password_encrypted: "nope".into(), - email: None, - matrix_user_id: None, avatar: None, banner: None, + banned: None, + deleted: None, published: None, updated: None, - admin: false, - banned: Some(false), - 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, + local: None, private_key: None, public_key: None, last_refreshed_at: None, @@ -474,13 +471,13 @@ mod tests { 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 { name: community_name.to_owned(), title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, removed: None, deleted: None, updated: None, @@ -504,7 +501,7 @@ mod tests { name: post_name.to_owned(), url: None, body: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, community_id: inserted_community.id, removed: None, deleted: None, @@ -525,7 +522,7 @@ mod tests { let post_like_form = PostLikeForm { post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, score: 1, }; @@ -534,38 +531,38 @@ mod tests { let expected_post_like = PostLike { id: inserted_post_like.id, post_id: inserted_post.id, - user_id: inserted_user.id, + person_id: inserted_person.id, published: inserted_post_like.published, score: 1, }; - let read_post_listings_with_user = PostQueryBuilder::create(&conn) + let read_post_listings_with_person = PostQueryBuilder::create(&conn) .listing_type(&ListingType::Community) .sort(&SortType::New) .community_id(inserted_community.id) - .my_user_id(inserted_user.id) + .my_person_id(inserted_person.id) .list() .unwrap(); - let read_post_listings_no_user = PostQueryBuilder::create(&conn) + let read_post_listings_no_person = PostQueryBuilder::create(&conn) .listing_type(&ListingType::Community) .sort(&SortType::New) .community_id(inserted_community.id) .list() .unwrap(); - let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap(); - let read_post_listing_with_user = - PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap(); + let read_post_listing_no_person = PostView::read(&conn, inserted_post.id, None).unwrap(); + let read_post_listing_with_person = + PostView::read(&conn, inserted_post.id, Some(inserted_person.id)).unwrap(); let agg = PostAggregates::read(&conn, inserted_post.id).unwrap(); - // the non user version - let expected_post_listing_no_user = PostView { + // the non person version + let expected_post_listing_no_person = PostView { post: Post { id: inserted_post.id, name: post_name, - creator_id: inserted_user.id, + creator_id: inserted_person.id, url: None, body: None, published: inserted_post.published, @@ -584,22 +581,20 @@ mod tests { local: true, }, my_vote: None, - creator: UserSafe { - id: inserted_user.id, - name: user_name, + creator: PersonSafe { + id: inserted_person.id, + name: person_name, preferred_username: None, - published: inserted_user.published, + published: inserted_person.published, avatar: None, - actor_id: inserted_user.actor_id.to_owned(), + actor_id: inserted_person.actor_id.to_owned(), local: true, banned: false, deleted: false, bio: None, banner: None, - admin: false, updated: None, - matrix_user_id: None, - inbox_url: inserted_user.inbox_url.to_owned(), + inbox_url: inserted_person.inbox_url.to_owned(), shared_inbox_url: None, }, creator_banned_from_community: false, @@ -614,7 +609,7 @@ mod tests { local: true, title: "nada".to_owned(), description: None, - creator_id: inserted_user.id, + creator_id: inserted_person.id, updated: None, banner: None, published: inserted_community.published, @@ -637,26 +632,32 @@ mod tests { }; // TODO More needs to be added here - let mut expected_post_listing_with_user = expected_post_listing_no_user.to_owned(); + let mut expected_post_listing_with_user = expected_post_listing_no_person.to_owned(); expected_post_listing_with_user.my_vote = Some(1); - 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 num_deleted = Post::delete(&conn, inserted_post.id).unwrap(); Community::delete(&conn, inserted_community.id).unwrap(); - User_::delete(&conn, inserted_user.id).unwrap(); + Person::delete(&conn, inserted_person.id).unwrap(); // The with user assert_eq!( expected_post_listing_with_user, - read_post_listings_with_user[0] + read_post_listings_with_person[0] ); - assert_eq!(expected_post_listing_with_user, read_post_listing_with_user); - assert_eq!(1, read_post_listings_with_user.len()); + assert_eq!( + expected_post_listing_with_user, + read_post_listing_with_person + ); + assert_eq!(1, read_post_listings_with_person.len()); // Without the user - assert_eq!(expected_post_listing_no_user, read_post_listings_no_user[0]); - assert_eq!(expected_post_listing_no_user, read_post_listing_no_user); - assert_eq!(1, read_post_listings_no_user.len()); + assert_eq!( + expected_post_listing_no_person, + read_post_listings_no_person[0] + ); + assert_eq!(expected_post_listing_no_person, read_post_listing_no_person); + assert_eq!(1, read_post_listings_no_person.len()); // assert_eq!(expected_post, inserted_post); // assert_eq!(expected_post, updated_post); diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index 578af80e9..5cef7364e 100644 --- a/crates/db_views/src/private_message_view.rs +++ b/crates/db_views/src/private_message_view.rs @@ -1,11 +1,13 @@ use diesel::{pg::Pg, result::Error, *}; use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{private_message, user_, user_alias_1}, + schema::{person, person_alias_1, private_message}, source::{ + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, private_message::PrivateMessage, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, }, + PersonId, + PrivateMessageId, }; use log::debug; use serde::Serialize; @@ -13,23 +15,23 @@ use serde::Serialize; #[derive(Debug, PartialEq, Serialize, Clone)] pub struct PrivateMessageView { pub private_message: PrivateMessage, - pub creator: UserSafe, - pub recipient: UserSafeAlias1, + pub creator: PersonSafe, + pub recipient: PersonSafeAlias1, } -type PrivateMessageViewTuple = (PrivateMessage, UserSafe, UserSafeAlias1); +type PrivateMessageViewTuple = (PrivateMessage, PersonSafe, PersonSafeAlias1); impl PrivateMessageView { - pub fn read(conn: &PgConnection, private_message_id: i32) -> Result { + pub fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result { let (private_message, creator, recipient) = private_message::table .find(private_message_id) - .inner_join(user_::table.on(private_message::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(private_message::recipient_id.eq(user_alias_1::id))) + .inner_join(person::table.on(private_message::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id))) .order_by(private_message::published.desc()) .select(( private_message::all_columns, - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .first::(conn)?; @@ -43,14 +45,14 @@ impl PrivateMessageView { pub struct PrivateMessageQueryBuilder<'a> { conn: &'a PgConnection, - recipient_id: i32, + recipient_id: PersonId, unread_only: bool, page: Option, limit: Option, } impl<'a> PrivateMessageQueryBuilder<'a> { - pub fn create(conn: &'a PgConnection, recipient_id: i32) -> Self { + pub fn create(conn: &'a PgConnection, recipient_id: PersonId) -> Self { PrivateMessageQueryBuilder { conn, recipient_id, @@ -77,12 +79,12 @@ impl<'a> PrivateMessageQueryBuilder<'a> { pub fn list(self) -> Result, Error> { let mut query = private_message::table - .inner_join(user_::table.on(private_message::creator_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(private_message::recipient_id.eq(user_alias_1::id))) + .inner_join(person::table.on(private_message::creator_id.eq(person::id))) + .inner_join(person_alias_1::table.on(private_message::recipient_id.eq(person_alias_1::id))) .select(( private_message::all_columns, - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .into_boxed(); diff --git a/crates/db_views/src/site_view.rs b/crates/db_views/src/site_view.rs index c04e85e9c..87fded01b 100644 --- a/crates/db_views/src/site_view.rs +++ b/crates/db_views/src/site_view.rs @@ -1,10 +1,10 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{aggregates::site_aggregates::SiteAggregates, ToSafe}; use lemmy_db_schema::{ - schema::{site, site_aggregates, user_}, + schema::{person, site, site_aggregates}, source::{ + person::{Person, PersonSafe}, site::Site, - user::{UserSafe, User_}, }, }; use serde::Serialize; @@ -12,21 +12,21 @@ use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct SiteView { pub site: Site, - pub creator: UserSafe, + pub creator: PersonSafe, pub counts: SiteAggregates, } impl SiteView { pub fn read(conn: &PgConnection) -> Result { let (site, creator, counts) = site::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(site_aggregates::table) .select(( site::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), site_aggregates::all_columns, )) - .first::<(Site, UserSafe, SiteAggregates)>(conn)?; + .first::<(Site, PersonSafe, SiteAggregates)>(conn)?; Ok(SiteView { site, diff --git a/crates/db_views_actor/src/community_follower_view.rs b/crates/db_views_actor/src/community_follower_view.rs index a4f2b20dc..730824194 100644 --- a/crates/db_views_actor/src/community_follower_view.rs +++ b/crates/db_views_actor/src/community_follower_view.rs @@ -1,28 +1,33 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, community_follower, user_}, + schema::{community, community_follower, person}, source::{ community::{Community, CommunitySafe}, - user::{UserSafe, User_}, + person::{Person, PersonSafe}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct CommunityFollowerView { pub community: CommunitySafe, - pub follower: UserSafe, + pub follower: PersonSafe, } -type CommunityFollowerViewTuple = (CommunitySafe, UserSafe); +type CommunityFollowerViewTuple = (CommunitySafe, PersonSafe); impl CommunityFollowerView { - pub fn for_community(conn: &PgConnection, community_id: i32) -> Result, Error> { + pub fn for_community(conn: &PgConnection, community_id: CommunityId) -> Result, Error> { let res = community_follower::table .inner_join(community::table) - .inner_join(user_::table) - .select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) .filter(community_follower::community_id.eq(community_id)) .order_by(community_follower::published) .load::(conn)?; @@ -30,12 +35,15 @@ impl CommunityFollowerView { Ok(Self::from_tuple_to_vec(res)) } - pub fn for_user(conn: &PgConnection, user_id: i32) -> Result, Error> { + pub fn for_person(conn: &PgConnection, person_id: PersonId) -> Result, Error> { let res = community_follower::table .inner_join(community::table) - .inner_join(user_::table) - .select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) - .filter(community_follower::user_id.eq(user_id)) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) + .filter(community_follower::person_id.eq(person_id)) .order_by(community_follower::published) .load::(conn)?; diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index fe8b3c222..274f68243 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -1,28 +1,33 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, community_moderator, user_}, + schema::{community, community_moderator, person}, source::{ community::{Community, CommunitySafe}, - user::{UserSafe, User_}, + person::{Person, PersonSafe}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct CommunityModeratorView { pub community: CommunitySafe, - pub moderator: UserSafe, + pub moderator: PersonSafe, } -type CommunityModeratorViewTuple = (CommunitySafe, UserSafe); +type CommunityModeratorViewTuple = (CommunitySafe, PersonSafe); impl CommunityModeratorView { - pub fn for_community(conn: &PgConnection, community_id: i32) -> Result, Error> { + pub fn for_community(conn: &PgConnection, community_id: CommunityId) -> Result, Error> { let res = community_moderator::table .inner_join(community::table) - .inner_join(user_::table) - .select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) .filter(community_moderator::community_id.eq(community_id)) .order_by(community_moderator::published) .load::(conn)?; @@ -30,12 +35,15 @@ impl CommunityModeratorView { Ok(Self::from_tuple_to_vec(res)) } - pub fn for_user(conn: &PgConnection, user_id: i32) -> Result, Error> { + pub fn for_person(conn: &PgConnection, person_id: PersonId) -> Result, Error> { let res = community_moderator::table .inner_join(community::table) - .inner_join(user_::table) - .select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) - .filter(community_moderator::user_id.eq(user_id)) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) + .filter(community_moderator::person_id.eq(person_id)) .order_by(community_moderator::published) .load::(conn)?; diff --git a/crates/db_views_actor/src/community_person_ban_view.rs b/crates/db_views_actor/src/community_person_ban_view.rs new file mode 100644 index 000000000..4db967239 --- /dev/null +++ b/crates/db_views_actor/src/community_person_ban_view.rs @@ -0,0 +1,40 @@ +use diesel::{result::Error, *}; +use lemmy_db_queries::ToSafe; +use lemmy_db_schema::{ + schema::{community, community_person_ban, person}, + source::{ + community::{Community, CommunitySafe}, + person::{Person, PersonSafe}, + }, + CommunityId, + PersonId, +}; +use serde::Serialize; + +#[derive(Debug, Serialize, Clone)] +pub struct CommunityPersonBanView { + pub community: CommunitySafe, + pub person: PersonSafe, +} + +impl CommunityPersonBanView { + pub fn get( + conn: &PgConnection, + from_person_id: PersonId, + from_community_id: CommunityId, + ) -> Result { + let (community, person) = community_person_ban::table + .inner_join(community::table) + .inner_join(person::table) + .select(( + Community::safe_columns_tuple(), + Person::safe_columns_tuple(), + )) + .filter(community_person_ban::community_id.eq(from_community_id)) + .filter(community_person_ban::person_id.eq(from_person_id)) + .order_by(community_person_ban::published) + .first::<(CommunitySafe, PersonSafe)>(conn)?; + + Ok(CommunityPersonBanView { community, person }) + } +} diff --git a/crates/db_views_actor/src/community_user_ban_view.rs b/crates/db_views_actor/src/community_user_ban_view.rs deleted file mode 100644 index d0a925848..000000000 --- a/crates/db_views_actor/src/community_user_ban_view.rs +++ /dev/null @@ -1,35 +0,0 @@ -use diesel::{result::Error, *}; -use lemmy_db_queries::ToSafe; -use lemmy_db_schema::{ - schema::{community, community_user_ban, user_}, - source::{ - community::{Community, CommunitySafe}, - user::{UserSafe, User_}, - }, -}; -use serde::Serialize; - -#[derive(Debug, Serialize, Clone)] -pub struct CommunityUserBanView { - pub community: CommunitySafe, - pub user: UserSafe, -} - -impl CommunityUserBanView { - pub fn get( - conn: &PgConnection, - from_user_id: i32, - from_community_id: i32, - ) -> Result { - let (community, user) = community_user_ban::table - .inner_join(community::table) - .inner_join(user_::table) - .select((Community::safe_columns_tuple(), User_::safe_columns_tuple())) - .filter(community_user_ban::community_id.eq(from_community_id)) - .filter(community_user_ban::user_id.eq(from_user_id)) - .order_by(community_user_ban::published) - .first::<(CommunitySafe, UserSafe)>(conn)?; - - Ok(CommunityUserBanView { community, user }) - } -} diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index 9187696db..fe3a80bb7 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -1,4 +1,4 @@ -use crate::{community_moderator_view::CommunityModeratorView, user_view::UserViewSafe}; +use crate::{community_moderator_view::CommunityModeratorView, person_view::PersonViewSafe}; use diesel::{result::Error, *}; use lemmy_db_queries::{ aggregates::community_aggregates::CommunityAggregates, @@ -12,25 +12,27 @@ use lemmy_db_queries::{ ViewToVec, }; use lemmy_db_schema::{ - schema::{community, community_aggregates, community_follower, user_}, + schema::{community, community_aggregates, community_follower, person}, source::{ community::{Community, CommunityFollower, CommunitySafe}, - user::{UserSafe, User_}, + person::{Person, PersonSafe}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct CommunityView { pub community: CommunitySafe, - pub creator: UserSafe, + pub creator: PersonSafe, pub subscribed: bool, pub counts: CommunityAggregates, } type CommunityViewTuple = ( CommunitySafe, - UserSafe, + PersonSafe, CommunityAggregates, Option, ); @@ -38,26 +40,26 @@ type CommunityViewTuple = ( impl CommunityView { pub fn read( conn: &PgConnection, - community_id: i32, - my_user_id: Option, + community_id: CommunityId, + my_person_id: Option, ) -> Result { // The left join below will return None in this case - let user_id_join = my_user_id.unwrap_or(-1); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let (community, creator, counts, follower) = community::table .find(community_id) - .inner_join(user_::table) + .inner_join(person::table) .inner_join(community_aggregates::table) .left_join( community_follower::table.on( community::id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .select(( Community::safe_columns_tuple(), - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), community_aggregates::all_columns, community_follower::all_columns.nullable(), )) @@ -72,21 +74,29 @@ impl CommunityView { } // TODO: this function is only used by is_mod_or_admin() below, can probably be merged - fn community_mods_and_admins(conn: &PgConnection, community_id: i32) -> Result, Error> { - let mut mods_and_admins: Vec = Vec::new(); + fn community_mods_and_admins( + conn: &PgConnection, + community_id: CommunityId, + ) -> Result, Error> { + let mut mods_and_admins: Vec = Vec::new(); mods_and_admins.append( &mut CommunityModeratorView::for_community(conn, community_id) .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?, ); - mods_and_admins - .append(&mut UserViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.user.id).collect())?); + mods_and_admins.append( + &mut PersonViewSafe::admins(conn).map(|v| v.into_iter().map(|a| a.person.id).collect())?, + ); Ok(mods_and_admins) } - pub fn is_mod_or_admin(conn: &PgConnection, user_id: i32, community_id: i32) -> bool { + pub fn is_mod_or_admin( + conn: &PgConnection, + person_id: PersonId, + community_id: CommunityId, + ) -> bool { Self::community_mods_and_admins(conn, community_id) .unwrap_or_default() - .contains(&user_id) + .contains(&person_id) } } @@ -94,7 +104,7 @@ pub struct CommunityQueryBuilder<'a> { conn: &'a PgConnection, listing_type: &'a ListingType, sort: &'a SortType, - my_user_id: Option, + my_person_id: Option, show_nsfw: bool, search_term: Option, page: Option, @@ -105,7 +115,7 @@ impl<'a> CommunityQueryBuilder<'a> { pub fn create(conn: &'a PgConnection) -> Self { CommunityQueryBuilder { conn, - my_user_id: None, + my_person_id: None, listing_type: &ListingType::All, sort: &SortType::Hot, show_nsfw: true, @@ -135,8 +145,8 @@ impl<'a> CommunityQueryBuilder<'a> { self } - pub fn my_user_id>(mut self, my_user_id: T) -> Self { - self.my_user_id = my_user_id.get_optional(); + pub fn my_person_id>(mut self, my_person_id: T) -> Self { + self.my_person_id = my_person_id.get_optional(); self } @@ -152,21 +162,21 @@ impl<'a> CommunityQueryBuilder<'a> { pub fn list(self) -> Result, Error> { // The left join below will return None in this case - let user_id_join = self.my_user_id.unwrap_or(-1); + let person_id_join = self.my_person_id.unwrap_or(PersonId(-1)); let mut query = community::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(community_aggregates::table) .left_join( community_follower::table.on( community::id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .select(( Community::safe_columns_tuple(), - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), community_aggregates::all_columns, community_follower::all_columns.nullable(), )) @@ -202,7 +212,7 @@ impl<'a> CommunityQueryBuilder<'a> { }; query = match self.listing_type { - ListingType::Subscribed => query.filter(community_follower::user_id.is_not_null()), // TODO could be this: and(community_follower::user_id.eq(user_id_join)), + ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Local => query.filter(community::local.eq(true)), _ => query, }; diff --git a/crates/db_views_actor/src/lib.rs b/crates/db_views_actor/src/lib.rs index a2ac31937..5d5203c56 100644 --- a/crates/db_views_actor/src/lib.rs +++ b/crates/db_views_actor/src/lib.rs @@ -1,6 +1,6 @@ pub mod community_follower_view; pub mod community_moderator_view; -pub mod community_user_ban_view; +pub mod community_person_ban_view; pub mod community_view; -pub mod user_mention_view; -pub mod user_view; +pub mod person_mention_view; +pub mod person_view; diff --git a/crates/db_views_actor/src/user_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs similarity index 67% rename from crates/db_views_actor/src/user_mention_view.rs rename to crates/db_views_actor/src/person_mention_view.rs index ffdbe0300..958d084be 100644 --- a/crates/db_views_actor/src/user_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -16,62 +16,64 @@ use lemmy_db_schema::{ comment_saved, community, community_follower, - community_user_ban, + community_person_ban, + person, + person_alias_1, + person_mention, post, - user_, - user_alias_1, - user_mention, }, source::{ comment::{Comment, CommentSaved}, - community::{Community, CommunityFollower, CommunitySafe, CommunityUserBan}, + community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, + person_mention::PersonMention, post::Post, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, - user_mention::UserMention, }, + PersonId, + PersonMentionId, }; use serde::Serialize; #[derive(Debug, PartialEq, Serialize, Clone)] -pub struct UserMentionView { - pub user_mention: UserMention, +pub struct PersonMentionView { + pub person_mention: PersonMention, pub comment: Comment, - pub creator: UserSafe, + pub creator: PersonSafe, pub post: Post, pub community: CommunitySafe, - pub recipient: UserSafeAlias1, + pub recipient: PersonSafeAlias1, pub counts: CommentAggregates, - pub creator_banned_from_community: bool, // Left Join to CommunityUserBan + pub creator_banned_from_community: bool, // Left Join to CommunityPersonBan pub subscribed: bool, // Left join to CommunityFollower pub saved: bool, // Left join to CommentSaved pub my_vote: Option, // Left join to CommentLike } -type UserMentionViewTuple = ( - UserMention, +type PersonMentionViewTuple = ( + PersonMention, Comment, - UserSafe, + PersonSafe, Post, CommunitySafe, - UserSafeAlias1, + PersonSafeAlias1, CommentAggregates, - Option, + Option, Option, Option, Option, ); -impl UserMentionView { +impl PersonMentionView { pub fn read( conn: &PgConnection, - user_mention_id: i32, - my_user_id: Option, + person_mention_id: PersonMentionId, + my_person_id: Option, ) -> Result { // The left join below will return None in this case - let user_id_join = my_user_id.unwrap_or(-1); + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); let ( - user_mention, + person_mention, comment, creator, post, @@ -82,59 +84,59 @@ impl UserMentionView { subscribed, saved, my_vote, - ) = user_mention::table - .find(user_mention_id) + ) = person_mention::table + .find(person_mention_id) .inner_join(comment::table) - .inner_join(user_::table.on(comment::creator_id.eq(user_::id))) + .inner_join(person::table.on(comment::creator_id.eq(person::id))) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_alias_1::table) + .inner_join(person_alias_1::table) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( community::id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(comment::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(comment::creator_id)), ), ) .left_join( community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( comment_saved::table.on( comment::id .eq(comment_saved::comment_id) - .and(comment_saved::user_id.eq(user_id_join)), + .and(comment_saved::person_id.eq(person_id_join)), ), ) .left_join( comment_like::table.on( comment::id .eq(comment_like::comment_id) - .and(comment_like::user_id.eq(user_id_join)), + .and(comment_like::person_id.eq(person_id_join)), ), ) .select(( - user_mention::all_columns, + person_mention::all_columns, comment::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), comment_aggregates::all_columns, - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), community_follower::all_columns.nullable(), comment_saved::all_columns.nullable(), comment_like::score.nullable(), )) - .first::(conn)?; + .first::(conn)?; - Ok(UserMentionView { - user_mention, + Ok(PersonMentionView { + person_mention, comment, creator, post, @@ -149,21 +151,21 @@ impl UserMentionView { } } -pub struct UserMentionQueryBuilder<'a> { +pub struct PersonMentionQueryBuilder<'a> { conn: &'a PgConnection, - my_user_id: Option, - recipient_id: Option, + my_person_id: Option, + recipient_id: Option, sort: &'a SortType, unread_only: bool, page: Option, limit: Option, } -impl<'a> UserMentionQueryBuilder<'a> { +impl<'a> PersonMentionQueryBuilder<'a> { pub fn create(conn: &'a PgConnection) -> Self { - UserMentionQueryBuilder { + PersonMentionQueryBuilder { conn, - my_user_id: None, + my_person_id: None, recipient_id: None, sort: &SortType::New, unread_only: false, @@ -182,13 +184,13 @@ impl<'a> UserMentionQueryBuilder<'a> { self } - pub fn recipient_id>(mut self, recipient_id: T) -> Self { + pub fn recipient_id>(mut self, recipient_id: T) -> Self { self.recipient_id = recipient_id.get_optional(); self } - pub fn my_user_id>(mut self, my_user_id: T) -> Self { - self.my_user_id = my_user_id.get_optional(); + pub fn my_person_id>(mut self, my_person_id: T) -> Self { + self.my_person_id = my_person_id.get_optional(); self } @@ -202,56 +204,56 @@ impl<'a> UserMentionQueryBuilder<'a> { self } - pub fn list(self) -> Result, Error> { + pub fn list(self) -> Result, Error> { use diesel::dsl::*; // The left join below will return None in this case - let user_id_join = self.my_user_id.unwrap_or(-1); + let person_id_join = self.my_person_id.unwrap_or(PersonId(-1)); - let mut query = user_mention::table + let mut query = person_mention::table .inner_join(comment::table) - .inner_join(user_::table.on(comment::creator_id.eq(user_::id))) + .inner_join(person::table.on(comment::creator_id.eq(person::id))) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) - .inner_join(user_alias_1::table) + .inner_join(person_alias_1::table) .inner_join(comment_aggregates::table.on(comment::id.eq(comment_aggregates::comment_id))) .left_join( - community_user_ban::table.on( + community_person_ban::table.on( community::id - .eq(community_user_ban::community_id) - .and(community_user_ban::user_id.eq(comment::creator_id)), + .eq(community_person_ban::community_id) + .and(community_person_ban::person_id.eq(comment::creator_id)), ), ) .left_join( community_follower::table.on( post::community_id .eq(community_follower::community_id) - .and(community_follower::user_id.eq(user_id_join)), + .and(community_follower::person_id.eq(person_id_join)), ), ) .left_join( comment_saved::table.on( comment::id .eq(comment_saved::comment_id) - .and(comment_saved::user_id.eq(user_id_join)), + .and(comment_saved::person_id.eq(person_id_join)), ), ) .left_join( comment_like::table.on( comment::id .eq(comment_like::comment_id) - .and(comment_like::user_id.eq(user_id_join)), + .and(comment_like::person_id.eq(person_id_join)), ), ) .select(( - user_mention::all_columns, + person_mention::all_columns, comment::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), comment_aggregates::all_columns, - community_user_ban::all_columns.nullable(), + community_person_ban::all_columns.nullable(), community_follower::all_columns.nullable(), comment_saved::all_columns.nullable(), comment_like::score.nullable(), @@ -259,11 +261,11 @@ impl<'a> UserMentionQueryBuilder<'a> { .into_boxed(); if let Some(recipient_id) = self.recipient_id { - query = query.filter(user_mention::recipient_id.eq(recipient_id)); + query = query.filter(person_mention::recipient_id.eq(recipient_id)); } if self.unread_only { - query = query.filter(user_mention::read.eq(false)); + query = query.filter(person_mention::read.eq(false)); } query = match self.sort { @@ -293,19 +295,19 @@ impl<'a> UserMentionQueryBuilder<'a> { let res = query .limit(limit) .offset(offset) - .load::(self.conn)?; + .load::(self.conn)?; - Ok(UserMentionView::from_tuple_to_vec(res)) + Ok(PersonMentionView::from_tuple_to_vec(res)) } } -impl ViewToVec for UserMentionView { - type DbTuple = UserMentionViewTuple; +impl ViewToVec for PersonMentionView { + type DbTuple = PersonMentionViewTuple; fn from_tuple_to_vec(items: Vec) -> Vec { items .iter() .map(|a| Self { - user_mention: a.0.to_owned(), + person_mention: a.0.to_owned(), comment: a.1.to_owned(), creator: a.2.to_owned(), post: a.3.to_owned(), diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs new file mode 100644 index 000000000..a44a468c4 --- /dev/null +++ b/crates/db_views_actor/src/person_view.rs @@ -0,0 +1,153 @@ +use diesel::{dsl::*, result::Error, *}; +use lemmy_db_queries::{ + aggregates::person_aggregates::PersonAggregates, + fuzzy_search, + limit_and_offset, + MaybeOptional, + SortType, + ToSafe, + ViewToVec, +}; +use lemmy_db_schema::{ + schema::{local_user, person, person_aggregates}, + source::person::{Person, PersonSafe}, + PersonId, +}; +use serde::Serialize; + +#[derive(Debug, Serialize, Clone)] +pub struct PersonViewSafe { + pub person: PersonSafe, + pub counts: PersonAggregates, +} + +type PersonViewSafeTuple = (PersonSafe, PersonAggregates); + +impl PersonViewSafe { + pub fn read(conn: &PgConnection, person_id: PersonId) -> Result { + let (person, counts) = person::table + .find(person_id) + .inner_join(person_aggregates::table) + .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) + .first::(conn)?; + Ok(Self { person, counts }) + } + + pub fn admins(conn: &PgConnection) -> Result, Error> { + let admins = person::table + .inner_join(person_aggregates::table) + .inner_join(local_user::table) + .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) + .filter(local_user::admin.eq(true)) + .order_by(person::published) + .load::(conn)?; + + Ok(Self::from_tuple_to_vec(admins)) + } + + pub fn banned(conn: &PgConnection) -> Result, Error> { + let banned = person::table + .inner_join(person_aggregates::table) + .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) + .filter(person::banned.eq(true)) + .load::(conn)?; + + Ok(Self::from_tuple_to_vec(banned)) + } +} + +pub struct PersonQueryBuilder<'a> { + conn: &'a PgConnection, + sort: &'a SortType, + search_term: Option, + page: Option, + limit: Option, +} + +impl<'a> PersonQueryBuilder<'a> { + pub fn create(conn: &'a PgConnection) -> Self { + PersonQueryBuilder { + conn, + search_term: None, + sort: &SortType::Hot, + page: None, + limit: None, + } + } + + pub fn sort(mut self, sort: &'a SortType) -> Self { + self.sort = sort; + self + } + + pub fn search_term>(mut self, search_term: T) -> Self { + self.search_term = search_term.get_optional(); + self + } + + pub fn page>(mut self, page: T) -> Self { + self.page = page.get_optional(); + self + } + + pub fn limit>(mut self, limit: T) -> Self { + self.limit = limit.get_optional(); + self + } + + pub fn list(self) -> Result, Error> { + let mut query = person::table + .inner_join(person_aggregates::table) + .select((Person::safe_columns_tuple(), person_aggregates::all_columns)) + .into_boxed(); + + if let Some(search_term) = self.search_term { + query = query.filter(person::name.ilike(fuzzy_search(&search_term))); + } + + query = match self.sort { + SortType::Hot => query + .order_by(person_aggregates::comment_score.desc()) + .then_order_by(person::published.desc()), + SortType::Active => query + .order_by(person_aggregates::comment_score.desc()) + .then_order_by(person::published.desc()), + SortType::New | SortType::MostComments | SortType::NewComments => { + query.order_by(person::published.desc()) + } + SortType::TopAll => query.order_by(person_aggregates::comment_score.desc()), + SortType::TopYear => query + .filter(person::published.gt(now - 1.years())) + .order_by(person_aggregates::comment_score.desc()), + SortType::TopMonth => query + .filter(person::published.gt(now - 1.months())) + .order_by(person_aggregates::comment_score.desc()), + SortType::TopWeek => query + .filter(person::published.gt(now - 1.weeks())) + .order_by(person_aggregates::comment_score.desc()), + SortType::TopDay => query + .filter(person::published.gt(now - 1.days())) + .order_by(person_aggregates::comment_score.desc()), + }; + + let (limit, offset) = limit_and_offset(self.page, self.limit); + query = query.limit(limit).offset(offset); + + let res = query.load::(self.conn)?; + + Ok(PersonViewSafe::from_tuple_to_vec(res)) + } +} + +impl ViewToVec for PersonViewSafe { + type DbTuple = PersonViewSafeTuple; + fn from_tuple_to_vec(items: Vec) -> Vec { + items + .iter() + .map(|a| Self { + person: a.0.to_owned(), + counts: a.1.to_owned(), + }) + .collect::>() + } +} diff --git a/crates/db_views_actor/src/user_view.rs b/crates/db_views_actor/src/user_view.rs deleted file mode 100644 index bbe889a25..000000000 --- a/crates/db_views_actor/src/user_view.rs +++ /dev/null @@ -1,151 +0,0 @@ -use diesel::{dsl::*, result::Error, *}; -use lemmy_db_queries::{ - aggregates::user_aggregates::UserAggregates, - fuzzy_search, - limit_and_offset, - MaybeOptional, - SortType, - ToSafe, - ViewToVec, -}; -use lemmy_db_schema::{ - schema::{user_, user_aggregates}, - source::user::{UserSafe, User_}, -}; -use serde::Serialize; - -#[derive(Debug, Serialize, Clone)] -pub struct UserViewSafe { - pub user: UserSafe, - pub counts: UserAggregates, -} - -type UserViewSafeTuple = (UserSafe, UserAggregates); - -impl UserViewSafe { - pub fn read(conn: &PgConnection, id: i32) -> Result { - let (user, counts) = user_::table - .find(id) - .inner_join(user_aggregates::table) - .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) - .first::(conn)?; - Ok(Self { user, counts }) - } - - pub fn admins(conn: &PgConnection) -> Result, Error> { - let admins = user_::table - .inner_join(user_aggregates::table) - .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) - .filter(user_::admin.eq(true)) - .order_by(user_::published) - .load::(conn)?; - - Ok(Self::from_tuple_to_vec(admins)) - } - - pub fn banned(conn: &PgConnection) -> Result, Error> { - let banned = user_::table - .inner_join(user_aggregates::table) - .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) - .filter(user_::banned.eq(true)) - .load::(conn)?; - - Ok(Self::from_tuple_to_vec(banned)) - } -} - -pub struct UserQueryBuilder<'a> { - conn: &'a PgConnection, - sort: &'a SortType, - search_term: Option, - page: Option, - limit: Option, -} - -impl<'a> UserQueryBuilder<'a> { - pub fn create(conn: &'a PgConnection) -> Self { - UserQueryBuilder { - conn, - search_term: None, - sort: &SortType::Hot, - page: None, - limit: None, - } - } - - pub fn sort(mut self, sort: &'a SortType) -> Self { - self.sort = sort; - self - } - - pub fn search_term>(mut self, search_term: T) -> Self { - self.search_term = search_term.get_optional(); - self - } - - pub fn page>(mut self, page: T) -> Self { - self.page = page.get_optional(); - self - } - - pub fn limit>(mut self, limit: T) -> Self { - self.limit = limit.get_optional(); - self - } - - pub fn list(self) -> Result, Error> { - let mut query = user_::table - .inner_join(user_aggregates::table) - .select((User_::safe_columns_tuple(), user_aggregates::all_columns)) - .into_boxed(); - - if let Some(search_term) = self.search_term { - query = query.filter(user_::name.ilike(fuzzy_search(&search_term))); - } - - query = match self.sort { - SortType::Hot => query - .order_by(user_aggregates::comment_score.desc()) - .then_order_by(user_::published.desc()), - SortType::Active => query - .order_by(user_aggregates::comment_score.desc()) - .then_order_by(user_::published.desc()), - SortType::New | SortType::MostComments | SortType::NewComments => { - query.order_by(user_::published.desc()) - } - SortType::TopAll => query.order_by(user_aggregates::comment_score.desc()), - SortType::TopYear => query - .filter(user_::published.gt(now - 1.years())) - .order_by(user_aggregates::comment_score.desc()), - SortType::TopMonth => query - .filter(user_::published.gt(now - 1.months())) - .order_by(user_aggregates::comment_score.desc()), - SortType::TopWeek => query - .filter(user_::published.gt(now - 1.weeks())) - .order_by(user_aggregates::comment_score.desc()), - SortType::TopDay => query - .filter(user_::published.gt(now - 1.days())) - .order_by(user_aggregates::comment_score.desc()), - }; - - let (limit, offset) = limit_and_offset(self.page, self.limit); - query = query.limit(limit).offset(offset); - - let res = query.load::(self.conn)?; - - Ok(UserViewSafe::from_tuple_to_vec(res)) - } -} - -impl ViewToVec for UserViewSafe { - type DbTuple = UserViewSafeTuple; - fn from_tuple_to_vec(items: Vec) -> Vec { - items - .iter() - .map(|a| Self { - user: a.0.to_owned(), - counts: a.1.to_owned(), - }) - .collect::>() - } -} diff --git a/crates/db_views_moderator/src/mod_add_community_view.rs b/crates/db_views_moderator/src/mod_add_community_view.rs index dfb7de7e6..df56d8cb2 100644 --- a/crates/db_views_moderator/src/mod_add_community_view.rs +++ b/crates/db_views_moderator/src/mod_add_community_view.rs @@ -1,47 +1,51 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_add_community, user_, user_alias_1}, + schema::{community, mod_add_community, person, person_alias_1}, source::{ community::{Community, CommunitySafe}, moderator::ModAddCommunity, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModAddCommunityView { pub mod_add_community: ModAddCommunity, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub community: CommunitySafe, - pub modded_user: UserSafeAlias1, + pub modded_person: PersonSafeAlias1, } -type ModAddCommunityViewTuple = (ModAddCommunity, UserSafe, CommunitySafe, UserSafeAlias1); +type ModAddCommunityViewTuple = (ModAddCommunity, PersonSafe, CommunitySafe, PersonSafeAlias1); impl ModAddCommunityView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_add_community::table - .inner_join(user_::table.on(mod_add_community::mod_user_id.eq(user_::id))) + .inner_join(person::table.on(mod_add_community::mod_person_id.eq(person::id))) .inner_join(community::table) - .inner_join(user_alias_1::table.on(mod_add_community::other_user_id.eq(user_alias_1::id))) + .inner_join( + person_alias_1::table.on(mod_add_community::other_person_id.eq(person_alias_1::id)), + ) .select(( mod_add_community::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), Community::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .into_boxed(); - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_add_community::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_add_community::mod_person_id.eq(mod_person_id)); }; if let Some(community_id) = community_id { @@ -69,7 +73,7 @@ impl ViewToVec for ModAddCommunityView { mod_add_community: a.0.to_owned(), moderator: a.1.to_owned(), community: a.2.to_owned(), - modded_user: a.3.to_owned(), + modded_person: a.3.to_owned(), }) .collect::>() } diff --git a/crates/db_views_moderator/src/mod_add_view.rs b/crates/db_views_moderator/src/mod_add_view.rs index 06c7091cc..d4b5746b6 100644 --- a/crates/db_views_moderator/src/mod_add_view.rs +++ b/crates/db_views_moderator/src/mod_add_view.rs @@ -1,42 +1,43 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{mod_add, user_, user_alias_1}, + schema::{mod_add, person, person_alias_1}, source::{ moderator::ModAdd, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, }, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModAddView { pub mod_add: ModAdd, - pub moderator: UserSafe, - pub modded_user: UserSafeAlias1, + pub moderator: PersonSafe, + pub modded_person: PersonSafeAlias1, } -type ModAddViewTuple = (ModAdd, UserSafe, UserSafeAlias1); +type ModAddViewTuple = (ModAdd, PersonSafe, PersonSafeAlias1); impl ModAddView { pub fn list( conn: &PgConnection, - mod_user_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_add::table - .inner_join(user_::table.on(mod_add::mod_user_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(mod_add::other_user_id.eq(user_alias_1::id))) + .inner_join(person::table.on(mod_add::mod_person_id.eq(person::id))) + .inner_join(person_alias_1::table.on(mod_add::other_person_id.eq(person_alias_1::id))) .select(( mod_add::all_columns, - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .into_boxed(); - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_add::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_add::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); @@ -59,7 +60,7 @@ impl ViewToVec for ModAddView { .map(|a| Self { mod_add: a.0.to_owned(), moderator: a.1.to_owned(), - modded_user: a.2.to_owned(), + modded_person: a.2.to_owned(), }) .collect::>() } diff --git a/crates/db_views_moderator/src/mod_ban_from_community_view.rs b/crates/db_views_moderator/src/mod_ban_from_community_view.rs index 1d9b1fafd..82d336f17 100644 --- a/crates/db_views_moderator/src/mod_ban_from_community_view.rs +++ b/crates/db_views_moderator/src/mod_ban_from_community_view.rs @@ -1,49 +1,56 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_ban_from_community, user_, user_alias_1}, + schema::{community, mod_ban_from_community, person, person_alias_1}, source::{ community::{Community, CommunitySafe}, moderator::ModBanFromCommunity, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModBanFromCommunityView { pub mod_ban_from_community: ModBanFromCommunity, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub community: CommunitySafe, - pub banned_user: UserSafeAlias1, + pub banned_person: PersonSafeAlias1, } -type ModBanFromCommunityViewTuple = (ModBanFromCommunity, UserSafe, CommunitySafe, UserSafeAlias1); +type ModBanFromCommunityViewTuple = ( + ModBanFromCommunity, + PersonSafe, + CommunitySafe, + PersonSafeAlias1, +); impl ModBanFromCommunityView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_ban_from_community::table - .inner_join(user_::table.on(mod_ban_from_community::mod_user_id.eq(user_::id))) + .inner_join(person::table.on(mod_ban_from_community::mod_person_id.eq(person::id))) .inner_join(community::table) .inner_join( - user_alias_1::table.on(mod_ban_from_community::other_user_id.eq(user_alias_1::id)), + person_alias_1::table.on(mod_ban_from_community::other_person_id.eq(person_alias_1::id)), ) .select(( mod_ban_from_community::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), Community::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .into_boxed(); - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_ban_from_community::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_ban_from_community::mod_person_id.eq(mod_person_id)); }; if let Some(community_id) = community_id { @@ -71,7 +78,7 @@ impl ViewToVec for ModBanFromCommunityView { mod_ban_from_community: a.0.to_owned(), moderator: a.1.to_owned(), community: a.2.to_owned(), - banned_user: a.3.to_owned(), + banned_person: a.3.to_owned(), }) .collect::>() } diff --git a/crates/db_views_moderator/src/mod_ban_view.rs b/crates/db_views_moderator/src/mod_ban_view.rs index ff599e187..ff9629774 100644 --- a/crates/db_views_moderator/src/mod_ban_view.rs +++ b/crates/db_views_moderator/src/mod_ban_view.rs @@ -1,42 +1,43 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{mod_ban, user_, user_alias_1}, + schema::{mod_ban, person, person_alias_1}, source::{ moderator::ModBan, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, }, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModBanView { pub mod_ban: ModBan, - pub moderator: UserSafe, - pub banned_user: UserSafeAlias1, + pub moderator: PersonSafe, + pub banned_person: PersonSafeAlias1, } -type ModBanViewTuple = (ModBan, UserSafe, UserSafeAlias1); +type ModBanViewTuple = (ModBan, PersonSafe, PersonSafeAlias1); impl ModBanView { pub fn list( conn: &PgConnection, - mod_user_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_ban::table - .inner_join(user_::table.on(mod_ban::mod_user_id.eq(user_::id))) - .inner_join(user_alias_1::table.on(mod_ban::other_user_id.eq(user_alias_1::id))) + .inner_join(person::table.on(mod_ban::mod_person_id.eq(person::id))) + .inner_join(person_alias_1::table.on(mod_ban::other_person_id.eq(person_alias_1::id))) .select(( mod_ban::all_columns, - User_::safe_columns_tuple(), - UserAlias1::safe_columns_tuple(), + Person::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), )) .into_boxed(); - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_ban::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_ban::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); @@ -59,7 +60,7 @@ impl ViewToVec for ModBanView { .map(|a| Self { mod_ban: a.0.to_owned(), moderator: a.1.to_owned(), - banned_user: a.2.to_owned(), + banned_person: a.2.to_owned(), }) .collect::>() } diff --git a/crates/db_views_moderator/src/mod_lock_post_view.rs b/crates/db_views_moderator/src/mod_lock_post_view.rs index e6c697af7..2ce303ecb 100644 --- a/crates/db_views_moderator/src/mod_lock_post_view.rs +++ b/crates/db_views_moderator/src/mod_lock_post_view.rs @@ -1,41 +1,43 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_lock_post, post, user_}, + schema::{community, mod_lock_post, person, post}, source::{ community::{Community, CommunitySafe}, moderator::ModLockPost, + person::{Person, PersonSafe}, post::Post, - user::{UserSafe, User_}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModLockPostView { pub mod_lock_post: ModLockPost, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub post: Post, pub community: CommunitySafe, } -type ModLockPostViewTuple = (ModLockPost, UserSafe, Post, CommunitySafe); +type ModLockPostViewTuple = (ModLockPost, PersonSafe, Post, CommunitySafe); impl ModLockPostView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_lock_post::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .select(( mod_lock_post::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), )) @@ -45,8 +47,8 @@ impl ModLockPostView { query = query.filter(post::community_id.eq(community_id)); }; - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_lock_post::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_lock_post::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); diff --git a/crates/db_views_moderator/src/mod_remove_comment_view.rs b/crates/db_views_moderator/src/mod_remove_comment_view.rs index 082703532..33b167b82 100644 --- a/crates/db_views_moderator/src/mod_remove_comment_view.rs +++ b/crates/db_views_moderator/src/mod_remove_comment_view.rs @@ -1,32 +1,34 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{comment, community, mod_remove_comment, post, user_, user_alias_1}, + schema::{comment, community, mod_remove_comment, person, person_alias_1, post}, source::{ comment::Comment, community::{Community, CommunitySafe}, moderator::ModRemoveComment, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, post::Post, - user::{UserAlias1, UserSafe, UserSafeAlias1, User_}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModRemoveCommentView { pub mod_remove_comment: ModRemoveComment, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub comment: Comment, - pub commenter: UserSafeAlias1, + pub commenter: PersonSafeAlias1, pub post: Post, pub community: CommunitySafe, } type ModRemoveCommentViewTuple = ( ModRemoveComment, - UserSafe, + PersonSafe, Comment, - UserSafeAlias1, + PersonSafeAlias1, Post, CommunitySafe, ); @@ -34,22 +36,22 @@ type ModRemoveCommentViewTuple = ( impl ModRemoveCommentView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_remove_comment::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(comment::table) - .inner_join(user_alias_1::table.on(comment::creator_id.eq(user_alias_1::id))) + .inner_join(person_alias_1::table.on(comment::creator_id.eq(person_alias_1::id))) .inner_join(post::table.on(comment::post_id.eq(post::id))) .inner_join(community::table.on(post::community_id.eq(community::id))) .select(( mod_remove_comment::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), comment::all_columns, - UserAlias1::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), )) @@ -59,8 +61,8 @@ impl ModRemoveCommentView { query = query.filter(post::community_id.eq(community_id)); }; - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_remove_comment::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_remove_comment::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); diff --git a/crates/db_views_moderator/src/mod_remove_community_view.rs b/crates/db_views_moderator/src/mod_remove_community_view.rs index ff62ac15f..34fd09828 100644 --- a/crates/db_views_moderator/src/mod_remove_community_view.rs +++ b/crates/db_views_moderator/src/mod_remove_community_view.rs @@ -1,43 +1,44 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_remove_community, user_}, + schema::{community, mod_remove_community, person}, source::{ community::{Community, CommunitySafe}, moderator::ModRemoveCommunity, - user::{UserSafe, User_}, + person::{Person, PersonSafe}, }, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModRemoveCommunityView { pub mod_remove_community: ModRemoveCommunity, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub community: CommunitySafe, } -type ModRemoveCommunityTuple = (ModRemoveCommunity, UserSafe, CommunitySafe); +type ModRemoveCommunityTuple = (ModRemoveCommunity, PersonSafe, CommunitySafe); impl ModRemoveCommunityView { pub fn list( conn: &PgConnection, - mod_user_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_remove_community::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(community::table) .select(( mod_remove_community::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), Community::safe_columns_tuple(), )) .into_boxed(); - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_remove_community::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_remove_community::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); diff --git a/crates/db_views_moderator/src/mod_remove_post_view.rs b/crates/db_views_moderator/src/mod_remove_post_view.rs index 530ae0396..ac34ff5eb 100644 --- a/crates/db_views_moderator/src/mod_remove_post_view.rs +++ b/crates/db_views_moderator/src/mod_remove_post_view.rs @@ -1,41 +1,43 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_remove_post, post, user_}, + schema::{community, mod_remove_post, person, post}, source::{ community::{Community, CommunitySafe}, moderator::ModRemovePost, + person::{Person, PersonSafe}, post::Post, - user::{UserSafe, User_}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModRemovePostView { pub mod_remove_post: ModRemovePost, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub post: Post, pub community: CommunitySafe, } -type ModRemovePostViewTuple = (ModRemovePost, UserSafe, Post, CommunitySafe); +type ModRemovePostViewTuple = (ModRemovePost, PersonSafe, Post, CommunitySafe); impl ModRemovePostView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_remove_post::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .select(( mod_remove_post::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), )) @@ -45,8 +47,8 @@ impl ModRemovePostView { query = query.filter(post::community_id.eq(community_id)); }; - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_remove_post::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_remove_post::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); diff --git a/crates/db_views_moderator/src/mod_sticky_post_view.rs b/crates/db_views_moderator/src/mod_sticky_post_view.rs index 1d726ca7c..411cb57af 100644 --- a/crates/db_views_moderator/src/mod_sticky_post_view.rs +++ b/crates/db_views_moderator/src/mod_sticky_post_view.rs @@ -1,41 +1,43 @@ use diesel::{result::Error, *}; use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; use lemmy_db_schema::{ - schema::{community, mod_sticky_post, post, user_}, + schema::{community, mod_sticky_post, person, post}, source::{ community::{Community, CommunitySafe}, moderator::ModStickyPost, + person::{Person, PersonSafe}, post::Post, - user::{UserSafe, User_}, }, + CommunityId, + PersonId, }; use serde::Serialize; #[derive(Debug, Serialize, Clone)] pub struct ModStickyPostView { pub mod_sticky_post: ModStickyPost, - pub moderator: UserSafe, + pub moderator: PersonSafe, pub post: Post, pub community: CommunitySafe, } -type ModStickyPostViewTuple = (ModStickyPost, UserSafe, Post, CommunitySafe); +type ModStickyPostViewTuple = (ModStickyPost, PersonSafe, Post, CommunitySafe); impl ModStickyPostView { pub fn list( conn: &PgConnection, - community_id: Option, - mod_user_id: Option, + community_id: Option, + mod_person_id: Option, page: Option, limit: Option, ) -> Result, Error> { let mut query = mod_sticky_post::table - .inner_join(user_::table) + .inner_join(person::table) .inner_join(post::table) .inner_join(community::table.on(post::community_id.eq(community::id))) .select(( mod_sticky_post::all_columns, - User_::safe_columns_tuple(), + Person::safe_columns_tuple(), post::all_columns, Community::safe_columns_tuple(), )) @@ -45,8 +47,8 @@ impl ModStickyPostView { query = query.filter(post::community_id.eq(community_id)); }; - if let Some(mod_user_id) = mod_user_id { - query = query.filter(mod_sticky_post::mod_user_id.eq(mod_user_id)); + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_sticky_post::mod_person_id.eq(mod_person_id)); }; let (limit, offset) = limit_and_offset(page, limit); diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 105f9662d..47aca46fd 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -4,17 +4,21 @@ use chrono::{DateTime, NaiveDateTime, Utc}; use diesel::PgConnection; use lemmy_api_structs::blocking; use lemmy_db_queries::{ - source::{community::Community_, user::User}, + source::{community::Community_, person::Person_}, + Crud, ListingType, SortType, }; -use lemmy_db_schema::source::{community::Community, user::User_}; +use lemmy_db_schema::{ + source::{community::Community, local_user::LocalUser, person::Person}, + LocalUserId, +}; use lemmy_db_views::{ comment_view::{CommentQueryBuilder, CommentView}, post_view::{PostQueryBuilder, PostView}, site_view::SiteView, }; -use lemmy_db_views_actor::user_mention_view::{UserMentionQueryBuilder, UserMentionView}; +use lemmy_db_views_actor::person_mention_view::{PersonMentionQueryBuilder, PersonMentionView}; use lemmy_utils::{ claims::Claims, settings::structs::Settings, @@ -167,13 +171,12 @@ fn get_feed_user( user_name: String, ) -> Result { let site_view = SiteView::read(&conn)?; - let user = User_::find_by_username(&conn, &user_name)?; - let user_url = user.get_profile_url(&Settings::get().hostname()); + let person = Person::find_by_name(&conn, &user_name)?; let posts = PostQueryBuilder::create(&conn) .listing_type(&ListingType::All) .sort(sort_type) - .creator_id(user.id) + .creator_id(person.id) .list()?; let items = create_post_items(posts)?; @@ -181,8 +184,8 @@ fn get_feed_user( let mut channel_builder = ChannelBuilder::default(); channel_builder .namespaces(RSS_NAMESPACE.to_owned()) - .title(&format!("{} - {}", site_view.site.name, user.name)) - .link(user_url) + .title(&format!("{} - {}", site_view.site.name, person.name)) + .link(person.actor_id.to_string()) .items(items); Ok(channel_builder) @@ -224,11 +227,12 @@ fn get_feed_front( jwt: String, ) -> Result { let site_view = SiteView::read(&conn)?; - let user_id = Claims::decode(&jwt)?.claims.id; + let local_user_id = LocalUserId(Claims::decode(&jwt)?.claims.local_user_id); + let person_id = LocalUser::read(&conn, local_user_id)?.person_id; let posts = PostQueryBuilder::create(&conn) .listing_type(&ListingType::Subscribed) - .my_user_id(user_id) + .my_person_id(person_id) .sort(sort_type) .list()?; @@ -250,19 +254,20 @@ fn get_feed_front( fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result { let site_view = SiteView::read(&conn)?; - let user_id = Claims::decode(&jwt)?.claims.id; + let local_user_id = LocalUserId(Claims::decode(&jwt)?.claims.local_user_id); + let person_id = LocalUser::read(&conn, local_user_id)?.person_id; let sort = SortType::New; let replies = CommentQueryBuilder::create(&conn) - .recipient_id(user_id) - .my_user_id(user_id) + .recipient_id(person_id) + .my_person_id(person_id) .sort(&sort) .list()?; - let mentions = UserMentionQueryBuilder::create(&conn) - .recipient_id(user_id) - .my_user_id(user_id) + let mentions = PersonMentionQueryBuilder::create(&conn) + .recipient_id(person_id) + .my_person_id(person_id) .sort(&sort) .list()?; @@ -287,7 +292,7 @@ fn get_feed_inbox(conn: &PgConnection, jwt: String) -> Result, - mentions: Vec, + mentions: Vec, ) -> Result, LemmyError> { let mut reply_items: Vec = replies .iter() diff --git a/crates/routes/src/webfinger.rs b/crates/routes/src/webfinger.rs index e04437347..8ab2a5b6a 100644 --- a/crates/routes/src/webfinger.rs +++ b/crates/routes/src/webfinger.rs @@ -1,13 +1,13 @@ use actix_web::{error::ErrorBadRequest, web::Query, *}; use anyhow::anyhow; use lemmy_api_structs::{blocking, WebFingerLink, WebFingerResponse}; -use lemmy_db_queries::source::{community::Community_, user::User}; -use lemmy_db_schema::source::{community::Community, user::User_}; +use lemmy_db_queries::source::{community::Community_, person::Person_}; +use lemmy_db_schema::source::{community::Community, person::Person}; use lemmy_utils::{ settings::structs::Settings, LemmyError, WEBFINGER_COMMUNITY_REGEX, - WEBFINGER_USER_REGEX, + WEBFINGER_USERNAME_REGEX, }; use lemmy_websocket::LemmyContext; use serde::Deserialize; @@ -41,7 +41,7 @@ async fn get_webfinger_response( .map(|c| c.get(1)) .flatten(); - let user_regex_parsed = WEBFINGER_USER_REGEX + let username_regex_parsed = WEBFINGER_USERNAME_REGEX .captures(&info.resource) .map(|c| c.get(1)) .flatten(); @@ -55,11 +55,11 @@ async fn get_webfinger_response( .await? .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))? .actor_id - } else if let Some(user_name) = user_regex_parsed { - let user_name = user_name.as_str().to_owned(); - // Make sure the requested user exists. + } else if let Some(person_name) = username_regex_parsed { + let person_name = person_name.as_str().to_owned(); + // Make sure the requested person exists. blocking(context.pool(), move |conn| { - User_::read_from_name(conn, &user_name) + Person::find_by_name(conn, &person_name) }) .await? .map_err(|_| ErrorBadRequest(LemmyError::from(anyhow!("not_found"))))? diff --git a/crates/utils/src/claims.rs b/crates/utils/src/claims.rs index 3d9232e6b..e84f34f91 100644 --- a/crates/utils/src/claims.rs +++ b/crates/utils/src/claims.rs @@ -6,7 +6,7 @@ type Jwt = String; #[derive(Debug, Serialize, Deserialize)] pub struct Claims { - pub id: i32, + pub local_user_id: i32, pub iss: String, } @@ -23,9 +23,9 @@ impl Claims { ) } - pub fn jwt(user_id: i32, hostname: String) -> Result { + pub fn jwt(local_user_id: i32, hostname: String) -> Result { let my_claims = Claims { - id: user_id, + local_user_id, iss: hostname, }; encode( diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index bd2b56844..f917d9389 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -18,13 +18,19 @@ pub mod version; use crate::settings::structs::Settings; use http::StatusCode; use regex::Regex; +use std::fmt; use thiserror::Error; pub type ConnectionId = usize; -pub type PostId = i32; -pub type CommunityId = i32; -pub type UserId = i32; -pub type IpAddr = String; + +#[derive(PartialEq, Eq, Hash, Debug, Clone)] +pub struct IpAddr(pub String); + +impl fmt::Display for IpAddr { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.0) + } +} #[macro_export] macro_rules! location_info { @@ -87,7 +93,7 @@ lazy_static! { Settings::get().hostname() )) .expect("compile webfinger regex"); - pub static ref WEBFINGER_USER_REGEX: Regex = Regex::new(&format!( + pub static ref WEBFINGER_USERNAME_REGEX: Regex = Regex::new(&format!( "^acct:([a-z0-9_]{{3, 20}})@{}$", Settings::get().hostname() )) diff --git a/crates/utils/src/rate_limit/mod.rs b/crates/utils/src/rate_limit/mod.rs index d3e74ed5b..578384c63 100644 --- a/crates/utils/src/rate_limit/mod.rs +++ b/crates/utils/src/rate_limit/mod.rs @@ -1,6 +1,7 @@ use crate::{ settings::structs::{RateLimitConfig, Settings}, utils::get_ip, + IpAddr, LemmyError, }; use actix_web::dev::{Service, ServiceRequest, ServiceResponse, Transform}; @@ -62,7 +63,7 @@ impl RateLimit { impl RateLimited { pub async fn wrap( self, - ip_addr: String, + ip_addr: IpAddr, fut: impl Future>, ) -> Result where diff --git a/crates/utils/src/rate_limit/rate_limiter.rs b/crates/utils/src/rate_limit/rate_limiter.rs index 701d608bf..a965c79bb 100644 --- a/crates/utils/src/rate_limit/rate_limiter.rs +++ b/crates/utils/src/rate_limit/rate_limiter.rs @@ -32,7 +32,7 @@ impl Default for RateLimiter { } impl RateLimiter { - fn insert_ip(&mut self, ip: &str) { + fn insert_ip(&mut self, ip: &IpAddr) { for rate_limit_type in RateLimitType::iter() { if self.buckets.get(&rate_limit_type).is_none() { self.buckets.insert(rate_limit_type, HashMap::new()); @@ -41,7 +41,7 @@ impl RateLimiter { if let Some(bucket) = self.buckets.get_mut(&rate_limit_type) { if bucket.get(ip).is_none() { bucket.insert( - ip.to_string(), + ip.clone(), RateLimitBucket { last_checked: SystemTime::now(), allowance: -2f64, @@ -56,7 +56,7 @@ impl RateLimiter { pub(super) fn check_rate_limit_full( &mut self, type_: RateLimitType, - ip: &str, + ip: &IpAddr, rate: i32, per: i32, check_only: bool, diff --git a/crates/utils/src/utils.rs b/crates/utils/src/utils.rs index 33ea833d5..c53d6c7c2 100644 --- a/crates/utils/src/utils.rs +++ b/crates/utils/src/utils.rs @@ -1,4 +1,4 @@ -use crate::{settings::structs::Settings, ApiError}; +use crate::{settings::structs::Settings, ApiError, IpAddr}; use actix_web::dev::ConnectionInfo; use chrono::{DateTime, FixedOffset, NaiveDateTime}; use itertools::Itertools; @@ -122,12 +122,14 @@ pub fn is_valid_post_title(title: &str) -> bool { VALID_POST_TITLE_REGEX.is_match(title) } -pub fn get_ip(conn_info: &ConnectionInfo) -> String { - conn_info - .realip_remote_addr() - .unwrap_or("127.0.0.1:12345") - .split(':') - .next() - .unwrap_or("127.0.0.1") - .to_string() +pub fn get_ip(conn_info: &ConnectionInfo) -> IpAddr { + IpAddr( + conn_info + .realip_remote_addr() + .unwrap_or("127.0.0.1:12345") + .split(':') + .next() + .unwrap_or("127.0.0.1") + .to_string(), + ) } diff --git a/crates/utils/src/version.rs b/crates/utils/src/version.rs index a3074cb92..7e3d00073 100644 --- a/crates/utils/src/version.rs +++ b/crates/utils/src/version.rs @@ -1 +1 @@ -pub const VERSION: &str = "0.9.9"; +pub const VERSION: &str = "0.10.0-rc.5"; diff --git a/crates/websocket/src/chat_server.rs b/crates/websocket/src/chat_server.rs index 9978d1ec6..c9016a250 100644 --- a/crates/websocket/src/chat_server.rs +++ b/crates/websocket/src/chat_server.rs @@ -7,16 +7,14 @@ use diesel::{ PgConnection, }; use lemmy_api_structs::{comment::*, post::*}; +use lemmy_db_schema::{CommunityId, LocalUserId, PostId}; use lemmy_utils::{ location_info, rate_limit::RateLimit, ApiError, - CommunityId, ConnectionId, IpAddr, LemmyError, - PostId, - UserId, }; use rand::rngs::ThreadRng; use reqwest::Client; @@ -51,7 +49,7 @@ pub struct ChatServer { /// A map from user id to its connection ID for joined users. Remember a user can have multiple /// sessions (IE clients) - pub(super) user_rooms: HashMap>, + pub(super) user_rooms: HashMap>, pub(super) rng: ThreadRng, @@ -185,7 +183,11 @@ impl ChatServer { Ok(()) } - pub fn join_user_room(&mut self, user_id: UserId, id: ConnectionId) -> Result<(), LemmyError> { + pub fn join_user_room( + &mut self, + user_id: LocalUserId, + id: ConnectionId, + ) -> Result<(), LemmyError> { // remove session from all rooms for sessions in self.user_rooms.values_mut() { sessions.remove(&id); @@ -302,7 +304,7 @@ impl ChatServer { &self, op: &UserOperation, response: &Response, - recipient_id: UserId, + recipient_id: LocalUserId, websocket_id: Option, ) -> Result<(), LemmyError> where @@ -345,7 +347,12 @@ impl ChatServer { )?; // Send it to the community too - self.send_community_room_message(user_operation, &comment_post_sent, 0, websocket_id)?; + self.send_community_room_message( + user_operation, + &comment_post_sent, + CommunityId(0), + websocket_id, + )?; self.send_community_room_message( user_operation, &comment_post_sent, @@ -379,7 +386,7 @@ impl ChatServer { post_sent.post_view.my_vote = None; // Send it to /c/all and that community - self.send_community_room_message(user_operation, &post_sent, 0, websocket_id)?; + self.send_community_room_message(user_operation, &post_sent, CommunityId(0), websocket_id)?; self.send_community_room_message(user_operation, &post_sent, community_id, websocket_id)?; // Send it to the post room @@ -408,7 +415,7 @@ impl ChatServer { let ip: IpAddr = match self.sessions.get(&msg.id) { Some(info) => info.ip.to_owned(), - None => "blank_ip".to_string(), + None => IpAddr("blank_ip".to_string()), }; let context = LemmyContext { diff --git a/crates/websocket/src/handlers.rs b/crates/websocket/src/handlers.rs index 0762b9485..30cd9639b 100644 --- a/crates/websocket/src/handlers.rs +++ b/crates/websocket/src/handlers.rs @@ -4,6 +4,7 @@ use crate::{ }; use actix::{Actor, Context, Handler, ResponseFuture}; use lemmy_db_schema::naive_now; +use lemmy_utils::ConnectionId; use log::{error, info}; use rand::Rng; use serde::Serialize; @@ -19,7 +20,7 @@ impl Actor for ChatServer { /// /// Register new session and assign unique id to this session impl Handler for ChatServer { - type Result = usize; + type Result = ConnectionId; fn handle(&mut self, msg: Connect, _ctx: &mut Context) -> Self::Result { // register session with random id @@ -102,7 +103,12 @@ where fn handle(&mut self, msg: SendUserRoomMessage, _: &mut Context) { self - .send_user_room_message(&msg.op, &msg.response, msg.recipient_id, msg.websocket_id) + .send_user_room_message( + &msg.op, + &msg.response, + msg.local_recipient_id, + msg.websocket_id, + ) .ok(); } } @@ -155,7 +161,7 @@ impl Handler for ChatServer { type Result = (); fn handle(&mut self, msg: JoinUserRoom, _: &mut Context) { - self.join_user_room(msg.user_id, msg.id).ok(); + self.join_user_room(msg.local_user_id, msg.id).ok(); } } diff --git a/crates/websocket/src/lib.rs b/crates/websocket/src/lib.rs index 4723c7141..56b18a179 100644 --- a/crates/websocket/src/lib.rs +++ b/crates/websocket/src/lib.rs @@ -117,10 +117,10 @@ pub enum UserOperation { RemoveCommunity, FollowCommunity, GetFollowedCommunities, - GetUserDetails, + GetPersonDetails, GetReplies, - GetUserMentions, - MarkUserMentionAsRead, + GetPersonMentions, + MarkPersonMentionAsRead, GetModlog, BanFromCommunity, AddModToCommunity, @@ -128,7 +128,7 @@ pub enum UserOperation { EditSite, GetSite, AddAdmin, - BanUser, + BanPerson, Search, MarkAllAsRead, SaveUserSettings, diff --git a/crates/websocket/src/messages.rs b/crates/websocket/src/messages.rs index 89f3f2b3e..a1d4396bb 100644 --- a/crates/websocket/src/messages.rs +++ b/crates/websocket/src/messages.rs @@ -1,7 +1,8 @@ use crate::UserOperation; use actix::{prelude::*, Recipient}; use lemmy_api_structs::{comment::CommentResponse, post::PostResponse}; -use lemmy_utils::{CommunityId, ConnectionId, IpAddr, PostId, UserId}; +use lemmy_db_schema::{CommunityId, LocalUserId, PostId}; +use lemmy_utils::{ConnectionId, IpAddr}; use serde::{Deserialize, Serialize}; /// Chat server sends this messages to session @@ -50,7 +51,7 @@ pub struct SendAllMessage { pub struct SendUserRoomMessage { pub op: UserOperation, pub response: Response, - pub recipient_id: UserId, + pub local_recipient_id: LocalUserId, pub websocket_id: Option, } @@ -91,7 +92,7 @@ pub struct SendComment { #[derive(Message)] #[rtype(result = "()")] pub struct JoinUserRoom { - pub user_id: UserId, + pub local_user_id: LocalUserId, pub id: ConnectionId, } diff --git a/crates/websocket/src/routes.rs b/crates/websocket/src/routes.rs index 71ff36b19..8a487813e 100644 --- a/crates/websocket/src/routes.rs +++ b/crates/websocket/src/routes.rs @@ -6,7 +6,7 @@ use crate::{ use actix::prelude::*; use actix_web::*; use actix_web_actors::ws; -use lemmy_utils::utils::get_ip; +use lemmy_utils::{utils::get_ip, ConnectionId, IpAddr}; use log::{debug, error, info}; use std::time::{Duration, Instant}; @@ -36,8 +36,8 @@ pub async fn chat_route( struct WsSession { cs_addr: Addr, /// unique session id - id: usize, - ip: String, + id: ConnectionId, + ip: IpAddr, /// Client must send ping at least once per 10 seconds (CLIENT_TIMEOUT), /// otherwise we drop connection. hb: Instant, diff --git a/docker/dev/docker-compose.yml b/docker/dev/docker-compose.yml index a23f1e0ed..90a2c0a3c 100644 --- a/docker/dev/docker-compose.yml +++ b/docker/dev/docker-compose.yml @@ -17,7 +17,7 @@ services: - iframely lemmy-ui: - image: dessalines/lemmy-ui:0.9.9 + image: dessalines/lemmy-ui:0.10.0-rc.5 ports: - "1235:1234" restart: always @@ -42,7 +42,7 @@ services: restart: always pictrs: - image: asonix/pictrs:v0.2.5-r0 + image: asonix/pictrs:v0.2.6-r1 ports: - "8537:8080" user: 991:991 diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 142c4fa44..77382899c 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -23,13 +23,17 @@ services: pictrs: restart: always - image: asonix/pictrs:v0.2.5-r0 + image: asonix/pictrs:v0.2.6-r1 user: 991:991 volumes: - ./volumes/pictrs_alpha:/mnt lemmy-alpha-ui: +<<<<<<< HEAD image: lemmy-ui:test +======= + image: dessalines/lemmy-ui:0.10.0-rc.5 +>>>>>>> main environment: - LEMMY_INTERNAL_HOST=lemmy-alpha:8541 - LEMMY_EXTERNAL_HOST=localhost:8541 @@ -58,7 +62,11 @@ services: - ./volumes/postgres_alpha:/var/lib/postgresql/data lemmy-beta-ui: +<<<<<<< HEAD image: lemmy-ui:test +======= + image: dessalines/lemmy-ui:0.10.0-rc.5 +>>>>>>> main environment: - LEMMY_INTERNAL_HOST=lemmy-beta:8551 - LEMMY_EXTERNAL_HOST=localhost:8551 @@ -87,7 +95,11 @@ services: - ./volumes/postgres_beta:/var/lib/postgresql/data lemmy-gamma-ui: +<<<<<<< HEAD image: lemmy-ui:test +======= + image: dessalines/lemmy-ui:0.10.0-rc.5 +>>>>>>> main environment: - LEMMY_INTERNAL_HOST=lemmy-gamma:8561 - LEMMY_EXTERNAL_HOST=localhost:8561 @@ -117,7 +129,7 @@ services: # An instance with only an allowlist for beta lemmy-delta-ui: - image: dessalines/lemmy-ui:0.9.9 + image: dessalines/lemmy-ui:0.10.0-rc.5 environment: - LEMMY_INTERNAL_HOST=lemmy-delta:8571 - LEMMY_EXTERNAL_HOST=localhost:8571 @@ -147,7 +159,7 @@ services: # An instance who has a blocklist, with lemmy-alpha blocked lemmy-epsilon-ui: - image: dessalines/lemmy-ui:0.9.9 + image: dessalines/lemmy-ui:0.10.0-rc.5 environment: - LEMMY_INTERNAL_HOST=lemmy-epsilon:8581 - LEMMY_EXTERNAL_HOST=localhost:8581 diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml index e219bdef8..bc42bd563 100644 --- a/docker/prod/docker-compose.yml +++ b/docker/prod/docker-compose.yml @@ -12,7 +12,7 @@ services: restart: always lemmy: - image: dessalines/lemmy:0.9.9 + image: dessalines/lemmy:0.10.0-rc.5 ports: - "127.0.0.1:8536:8536" restart: always @@ -26,7 +26,7 @@ services: - iframely lemmy-ui: - image: dessalines/lemmy-ui:0.9.9 + image: dessalines/lemmy-ui:0.10.0-rc.5 ports: - "127.0.0.1:1235:1234" restart: always @@ -38,7 +38,7 @@ services: - lemmy pictrs: - image: asonix/pictrs:v0.2.5-r0 + image: asonix/pictrs:v0.2.6-r1 ports: - "127.0.0.1:8537:8080" user: 991:991 diff --git a/migrations/2021-03-09-171136_split_user_table_2/down.sql b/migrations/2021-03-09-171136_split_user_table_2/down.sql new file mode 100644 index 000000000..e1d55a205 --- /dev/null +++ b/migrations/2021-03-09-171136_split_user_table_2/down.sql @@ -0,0 +1,359 @@ +-- post_saved +alter table post_saved rename column person_id to user_id; +alter table post_saved rename constraint post_saved_post_id_person_id_key to post_saved_post_id_user_id_key; +alter table post_saved rename constraint post_saved_person_id_fkey to post_saved_user_id_fkey; + +-- post_read +alter table post_read rename column person_id to user_id; +alter table post_read rename constraint post_read_post_id_person_id_key to post_read_post_id_user_id_key; +alter table post_read rename constraint post_read_person_id_fkey to post_read_user_id_fkey; + +-- post_like +alter table post_like rename column person_id to user_id; +alter index idx_post_like_person rename to idx_post_like_user; +alter table post_like rename constraint post_like_post_id_person_id_key to post_like_post_id_user_id_key; +alter table post_like rename constraint post_like_person_id_fkey to post_like_user_id_fkey; + +-- password_reset_request +delete from password_reset_request; +alter table password_reset_request drop column local_user_id; +alter table password_reset_request add column user_id integer not null references person(id) on update cascade on delete cascade; + +-- mod_sticky_post +alter table mod_sticky_post rename column mod_person_id to mod_user_id; +alter table mod_sticky_post rename constraint mod_sticky_post_mod_person_id_fkey to mod_sticky_post_mod_user_id_fkey; + +-- mod_remove_post +alter table mod_remove_post rename column mod_person_id to mod_user_id; +alter table mod_remove_post rename constraint mod_remove_post_mod_person_id_fkey to mod_remove_post_mod_user_id_fkey; + +-- mod_remove_community +alter table mod_remove_community rename column mod_person_id to mod_user_id; +alter table mod_remove_community rename constraint mod_remove_community_mod_person_id_fkey to mod_remove_community_mod_user_id_fkey; + +-- mod_remove_comment +alter table mod_remove_comment rename column mod_person_id to mod_user_id; +alter table mod_remove_comment rename constraint mod_remove_comment_mod_person_id_fkey to mod_remove_comment_mod_user_id_fkey; + +-- mod_lock_post +alter table mod_lock_post rename column mod_person_id to mod_user_id; +alter table mod_lock_post rename constraint mod_lock_post_mod_person_id_fkey to mod_lock_post_mod_user_id_fkey; + +-- mod_add_community +alter table mod_ban_from_community rename column mod_person_id to mod_user_id; +alter table mod_ban_from_community rename column other_person_id to other_user_id; +alter table mod_ban_from_community rename constraint mod_ban_from_community_mod_person_id_fkey to mod_ban_from_community_mod_user_id_fkey; +alter table mod_ban_from_community rename constraint mod_ban_from_community_other_person_id_fkey to mod_ban_from_community_other_user_id_fkey; + +-- mod_ban +alter table mod_ban rename column mod_person_id to mod_user_id; +alter table mod_ban rename column other_person_id to other_user_id; +alter table mod_ban rename constraint mod_ban_mod_person_id_fkey to mod_ban_mod_user_id_fkey; +alter table mod_ban rename constraint mod_ban_other_person_id_fkey to mod_ban_other_user_id_fkey; + +-- mod_add_community +alter table mod_add_community rename column mod_person_id to mod_user_id; +alter table mod_add_community rename column other_person_id to other_user_id; +alter table mod_add_community rename constraint mod_add_community_mod_person_id_fkey to mod_add_community_mod_user_id_fkey; +alter table mod_add_community rename constraint mod_add_community_other_person_id_fkey to mod_add_community_other_user_id_fkey; + +-- mod_add +alter table mod_add rename column mod_person_id to mod_user_id; +alter table mod_add rename column other_person_id to other_user_id; +alter table mod_add rename constraint mod_add_mod_person_id_fkey to mod_add_mod_user_id_fkey; +alter table mod_add rename constraint mod_add_other_person_id_fkey to mod_add_other_user_id_fkey; + +-- community_user_ban +alter table community_person_ban rename to community_user_ban; +alter sequence community_person_ban_id_seq rename to community_user_ban_id_seq; +alter table community_user_ban rename column person_id to user_id; +alter table community_user_ban rename constraint community_person_ban_pkey to community_user_ban_pkey; +alter table community_user_ban rename constraint community_person_ban_community_id_fkey to community_user_ban_community_id_fkey; +alter table community_user_ban rename constraint community_person_ban_community_id_person_id_key to community_user_ban_community_id_user_id_key; +alter table community_user_ban rename constraint community_person_ban_person_id_fkey to community_user_ban_user_id_fkey; + +-- community_moderator +alter table community_moderator rename column person_id to user_id; +alter table community_moderator rename constraint community_moderator_community_id_person_id_key to community_moderator_community_id_user_id_key; +alter table community_moderator rename constraint community_moderator_person_id_fkey to community_moderator_user_id_fkey; + +-- community_follower +alter table community_follower rename column person_id to user_id; +alter table community_follower rename constraint community_follower_community_id_person_id_key to community_follower_community_id_user_id_key; +alter table community_follower rename constraint community_follower_person_id_fkey to community_follower_user_id_fkey; + +-- comment_saved +alter table comment_saved rename column person_id to user_id; +alter table comment_saved rename constraint comment_saved_comment_id_person_id_key to comment_saved_comment_id_user_id_key; +alter table comment_saved rename constraint comment_saved_person_id_fkey to comment_saved_user_id_fkey; + +-- comment_like +alter table comment_like rename column person_id to user_id; +alter index idx_comment_like_person rename to idx_comment_like_user; +alter table comment_like rename constraint comment_like_comment_id_person_id_key to comment_like_comment_id_user_id_key; +alter table comment_like rename constraint comment_like_person_id_fkey to comment_like_user_id_fkey; + +-- user_ban +alter table person_ban rename to user_ban; +alter sequence person_ban_id_seq rename to user_ban_id_seq; +alter index person_ban_pkey rename to user_ban_pkey; +alter index person_ban_person_id_key rename to user_ban_user_id_key; +alter table user_ban rename column person_id to user_id; +alter table user_ban rename constraint person_ban_person_id_fkey to user_ban_user_id_fkey; + +-- user_mention +alter table person_mention rename to user_mention; +alter sequence person_mention_id_seq rename to user_mention_id_seq; +alter index person_mention_pkey rename to user_mention_pkey; +alter index person_mention_recipient_id_comment_id_key rename to user_mention_recipient_id_comment_id_key; +alter table user_mention rename constraint person_mention_comment_id_fkey to user_mention_comment_id_fkey; +alter table user_mention rename constraint person_mention_recipient_id_fkey to user_mention_recipient_id_fkey; + +-- User aggregates table +alter table person_aggregates rename to user_aggregates; +alter sequence person_aggregates_id_seq rename to user_aggregates_id_seq; +alter table user_aggregates rename column person_id to user_id; + +-- Indexes +alter index person_aggregates_pkey rename to user_aggregates_pkey; +alter index idx_person_aggregates_comment_score rename to idx_user_aggregates_comment_score; +alter index person_aggregates_person_id_key rename to user_aggregates_user_id_key; +alter table user_aggregates rename constraint person_aggregates_person_id_fkey to user_aggregates_user_id_fkey; + +-- Redo the user_aggregates table +drop trigger person_aggregates_person on person; +drop trigger person_aggregates_post_count on post; +drop trigger person_aggregates_post_score on post_like; +drop trigger person_aggregates_comment_count on comment; +drop trigger person_aggregates_comment_score on comment_like; +drop function + person_aggregates_person, + person_aggregates_post_count, + person_aggregates_post_score, + person_aggregates_comment_count, + person_aggregates_comment_score; + +-- user_ table +-- Drop views +drop view person_alias_1, person_alias_2; + +-- Rename indexes +alter index person__pkey rename to user__pkey; +alter index idx_person_actor_id rename to idx_user_actor_id; +alter index idx_person_inbox_url rename to idx_user_inbox_url; +alter index idx_person_lower_actor_id rename to idx_user_lower_actor_id; +alter index idx_person_published rename to idx_user_published; + +-- Rename triggers +alter trigger site_aggregates_person_delete on person rename to site_aggregates_user_delete; +alter trigger site_aggregates_person_insert on person rename to site_aggregates_user_insert; + +-- Rename the trigger functions +alter function site_aggregates_person_delete() rename to site_aggregates_user_delete; +alter function site_aggregates_person_insert() rename to site_aggregates_user_insert; + +-- Rename the table back to user_ +alter table person rename to user_; +alter sequence person_id_seq rename to user__id_seq; + +-- Add the columns back in +alter table user_ + add column password_encrypted text not null default 'changeme', + add column email text, + add column admin boolean default false not null, + add column show_nsfw boolean default false not null, + add column theme character varying(20) default 'darkly'::character varying not null, + add column default_sort_type smallint default 0 not null, + add column default_listing_type smallint default 1 not null, + add column lang character varying(20) default 'browser'::character varying not null, + add column show_avatars boolean default true not null, + add column send_notifications_to_email boolean default false not null, + add column matrix_user_id text; + +-- Update the user_ table with the local_user data +update user_ u set + password_encrypted = lu.password_encrypted, + email = lu.email, + admin = lu.admin, + show_nsfw = lu.show_nsfw, + theme = lu.theme, + default_sort_type = lu.default_sort_type, + default_listing_type = lu.default_listing_type, + lang = lu.lang, + show_avatars = lu.show_avatars, + send_notifications_to_email = lu.send_notifications_to_email, + matrix_user_id = lu.matrix_user_id +from local_user lu +where lu.person_id = u.id; + +create view user_alias_1 as select * from user_; +create view user_alias_2 as select * from user_; + +drop table local_user; + +-- Add the user_aggregates table triggers + +-- initial user add +create function user_aggregates_user() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + insert into user_aggregates (user_id) values (NEW.id); + ELSIF (TG_OP = 'DELETE') THEN + delete from user_aggregates where user_id = OLD.id; + END IF; + return null; +end $$; + +create trigger user_aggregates_user +after insert or delete on user_ +for each row +execute procedure user_aggregates_user(); + +-- post count +create function user_aggregates_post_count() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + update user_aggregates + set post_count = post_count + 1 where user_id = NEW.creator_id; + + ELSIF (TG_OP = 'DELETE') THEN + update user_aggregates + set post_count = post_count - 1 where user_id = OLD.creator_id; + + -- If the post gets deleted, the score calculation trigger won't fire, + -- so you need to re-calculate + update user_aggregates ua + set post_score = pd.score + from ( + select u.id, + coalesce(0, sum(pl.score)) as score + -- User join because posts could be empty + from user_ u + left join post p on u.id = p.creator_id + left join post_like pl on p.id = pl.post_id + group by u.id + ) pd + where ua.user_id = OLD.creator_id; + + END IF; + return null; +end $$; + +create trigger user_aggregates_post_count +after insert or delete on post +for each row +execute procedure user_aggregates_post_count(); + +-- post score +create function user_aggregates_post_score() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + -- Need to get the post creator, not the voter + update user_aggregates ua + set post_score = post_score + NEW.score + from post p + where ua.user_id = p.creator_id and p.id = NEW.post_id; + + ELSIF (TG_OP = 'DELETE') THEN + update user_aggregates ua + set post_score = post_score - OLD.score + from post p + where ua.user_id = p.creator_id and p.id = OLD.post_id; + END IF; + return null; +end $$; + +create trigger user_aggregates_post_score +after insert or delete on post_like +for each row +execute procedure user_aggregates_post_score(); + +-- comment count +create function user_aggregates_comment_count() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + update user_aggregates + set comment_count = comment_count + 1 where user_id = NEW.creator_id; + ELSIF (TG_OP = 'DELETE') THEN + update user_aggregates + set comment_count = comment_count - 1 where user_id = OLD.creator_id; + + -- If the comment gets deleted, the score calculation trigger won't fire, + -- so you need to re-calculate + update user_aggregates ua + set comment_score = cd.score + from ( + select u.id, + coalesce(0, sum(cl.score)) as score + -- User join because comments could be empty + from user_ u + left join comment c on u.id = c.creator_id + left join comment_like cl on c.id = cl.comment_id + group by u.id + ) cd + where ua.user_id = OLD.creator_id; + END IF; + return null; +end $$; + +create trigger user_aggregates_comment_count +after insert or delete on comment +for each row +execute procedure user_aggregates_comment_count(); + +-- comment score +create function user_aggregates_comment_score() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + -- Need to get the post creator, not the voter + update user_aggregates ua + set comment_score = comment_score + NEW.score + from comment c + where ua.user_id = c.creator_id and c.id = NEW.comment_id; + ELSIF (TG_OP = 'DELETE') THEN + update user_aggregates ua + set comment_score = comment_score - OLD.score + from comment c + where ua.user_id = c.creator_id and c.id = OLD.comment_id; + END IF; + return null; +end $$; + +create trigger user_aggregates_comment_score +after insert or delete on comment_like +for each row +execute procedure user_aggregates_comment_score(); + +-- redo site aggregates trigger +create or replace function site_aggregates_activity(i text) returns integer + language plpgsql + as $$ +declare + count_ integer; +begin + select count(*) + into count_ + from ( + select c.creator_id from comment c + inner join user_ u on c.creator_id = u.id + where c.published > ('now'::timestamp - i::interval) + and u.local = true + union + select p.creator_id from post p + inner join user_ u on p.creator_id = u.id + where p.published > ('now'::timestamp - i::interval) + and u.local = true + ) a; + return count_; +end; +$$; diff --git a/migrations/2021-03-09-171136_split_user_table_2/up.sql b/migrations/2021-03-09-171136_split_user_table_2/up.sql new file mode 100644 index 000000000..db3547e5f --- /dev/null +++ b/migrations/2021-03-09-171136_split_user_table_2/up.sql @@ -0,0 +1,391 @@ +-- Person +-- Drop the 2 views user_alias_1, user_alias_2 +drop view user_alias_1, user_alias_2; + +-- rename the user_ table to person +alter table user_ rename to person; +alter sequence user__id_seq rename to person_id_seq; + +-- create a new table local_user +create table local_user ( + id serial primary key, + person_id int references person on update cascade on delete cascade not null, + password_encrypted text not null, + email text unique, + admin boolean default false not null, + show_nsfw boolean default false not null, + theme character varying(20) default 'darkly'::character varying not null, + default_sort_type smallint default 0 not null, + default_listing_type smallint default 1 not null, + lang character varying(20) default 'browser'::character varying not null, + show_avatars boolean default true not null, + send_notifications_to_email boolean default false not null, + matrix_user_id text, + unique (person_id) +); + +-- Copy the local users over to the new table +insert into local_user +( + person_id, + password_encrypted, + email, + admin, + show_nsfw, + theme, + default_sort_type, + default_listing_type, + lang, + show_avatars, + send_notifications_to_email, + matrix_user_id +) +select + id, + password_encrypted, + email, + admin, + show_nsfw, + theme, + default_sort_type, + default_listing_type, + lang, + show_avatars, + send_notifications_to_email, + matrix_user_id +from person +where local = true; + +-- Drop those columns from person +alter table person + drop column password_encrypted, + drop column email, + drop column admin, + drop column show_nsfw, + drop column theme, + drop column default_sort_type, + drop column default_listing_type, + drop column lang, + drop column show_avatars, + drop column send_notifications_to_email, + drop column matrix_user_id; + +-- Rename indexes +alter index user__pkey rename to person__pkey; +alter index idx_user_actor_id rename to idx_person_actor_id; +alter index idx_user_inbox_url rename to idx_person_inbox_url; +alter index idx_user_lower_actor_id rename to idx_person_lower_actor_id; +alter index idx_user_published rename to idx_person_published; + +-- Rename triggers +alter trigger site_aggregates_user_delete on person rename to site_aggregates_person_delete; +alter trigger site_aggregates_user_insert on person rename to site_aggregates_person_insert; + +-- Rename the trigger functions +alter function site_aggregates_user_delete() rename to site_aggregates_person_delete; +alter function site_aggregates_user_insert() rename to site_aggregates_person_insert; + +-- Create views +create view person_alias_1 as select * from person; +create view person_alias_2 as select * from person; + +-- Redo user aggregates into person_aggregates +alter table user_aggregates rename to person_aggregates; +alter sequence user_aggregates_id_seq rename to person_aggregates_id_seq; +alter table person_aggregates rename column user_id to person_id; + +-- index +alter index user_aggregates_pkey rename to person_aggregates_pkey; +alter index idx_user_aggregates_comment_score rename to idx_person_aggregates_comment_score; +alter index user_aggregates_user_id_key rename to person_aggregates_person_id_key; +alter table person_aggregates rename constraint user_aggregates_user_id_fkey to person_aggregates_person_id_fkey; + + +-- Drop all the old triggers and functions +drop trigger user_aggregates_user on person; +drop trigger user_aggregates_post_count on post; +drop trigger user_aggregates_post_score on post_like; +drop trigger user_aggregates_comment_count on comment; +drop trigger user_aggregates_comment_score on comment_like; +drop function + user_aggregates_user, + user_aggregates_post_count, + user_aggregates_post_score, + user_aggregates_comment_count, + user_aggregates_comment_score; + +-- initial user add +create function person_aggregates_person() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + insert into person_aggregates (person_id) values (NEW.id); + ELSIF (TG_OP = 'DELETE') THEN + delete from person_aggregates where person_id = OLD.id; + END IF; + return null; +end $$; + +create trigger person_aggregates_person +after insert or delete on person +for each row +execute procedure person_aggregates_person(); + +-- post count +create function person_aggregates_post_count() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + update person_aggregates + set post_count = post_count + 1 where person_id = NEW.creator_id; + + ELSIF (TG_OP = 'DELETE') THEN + update person_aggregates + set post_count = post_count - 1 where person_id = OLD.creator_id; + + -- If the post gets deleted, the score calculation trigger won't fire, + -- so you need to re-calculate + update person_aggregates ua + set post_score = pd.score + from ( + select u.id, + coalesce(0, sum(pl.score)) as score + -- User join because posts could be empty + from person u + left join post p on u.id = p.creator_id + left join post_like pl on p.id = pl.post_id + group by u.id + ) pd + where ua.person_id = OLD.creator_id; + + END IF; + return null; +end $$; + +create trigger person_aggregates_post_count +after insert or delete on post +for each row +execute procedure person_aggregates_post_count(); + +-- post score +create function person_aggregates_post_score() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + -- Need to get the post creator, not the voter + update person_aggregates ua + set post_score = post_score + NEW.score + from post p + where ua.person_id = p.creator_id and p.id = NEW.post_id; + + ELSIF (TG_OP = 'DELETE') THEN + update person_aggregates ua + set post_score = post_score - OLD.score + from post p + where ua.person_id = p.creator_id and p.id = OLD.post_id; + END IF; + return null; +end $$; + +create trigger person_aggregates_post_score +after insert or delete on post_like +for each row +execute procedure person_aggregates_post_score(); + +-- comment count +create function person_aggregates_comment_count() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + update person_aggregates + set comment_count = comment_count + 1 where person_id = NEW.creator_id; + ELSIF (TG_OP = 'DELETE') THEN + update person_aggregates + set comment_count = comment_count - 1 where person_id = OLD.creator_id; + + -- If the comment gets deleted, the score calculation trigger won't fire, + -- so you need to re-calculate + update person_aggregates ua + set comment_score = cd.score + from ( + select u.id, + coalesce(0, sum(cl.score)) as score + -- User join because comments could be empty + from person u + left join comment c on u.id = c.creator_id + left join comment_like cl on c.id = cl.comment_id + group by u.id + ) cd + where ua.person_id = OLD.creator_id; + END IF; + return null; +end $$; + +create trigger person_aggregates_comment_count +after insert or delete on comment +for each row +execute procedure person_aggregates_comment_count(); + +-- comment score +create function person_aggregates_comment_score() +returns trigger language plpgsql +as $$ +begin + IF (TG_OP = 'INSERT') THEN + -- Need to get the post creator, not the voter + update person_aggregates ua + set comment_score = comment_score + NEW.score + from comment c + where ua.person_id = c.creator_id and c.id = NEW.comment_id; + ELSIF (TG_OP = 'DELETE') THEN + update person_aggregates ua + set comment_score = comment_score - OLD.score + from comment c + where ua.person_id = c.creator_id and c.id = OLD.comment_id; + END IF; + return null; +end $$; + +create trigger person_aggregates_comment_score +after insert or delete on comment_like +for each row +execute procedure person_aggregates_comment_score(); + +-- person_mention +alter table user_mention rename to person_mention; +alter sequence user_mention_id_seq rename to person_mention_id_seq; +alter index user_mention_pkey rename to person_mention_pkey; +alter index user_mention_recipient_id_comment_id_key rename to person_mention_recipient_id_comment_id_key; +alter table person_mention rename constraint user_mention_comment_id_fkey to person_mention_comment_id_fkey; +alter table person_mention rename constraint user_mention_recipient_id_fkey to person_mention_recipient_id_fkey; + +-- user_ban +alter table user_ban rename to person_ban; +alter sequence user_ban_id_seq rename to person_ban_id_seq; +alter index user_ban_pkey rename to person_ban_pkey; +alter index user_ban_user_id_key rename to person_ban_person_id_key; +alter table person_ban rename column user_id to person_id; +alter table person_ban rename constraint user_ban_user_id_fkey to person_ban_person_id_fkey; + +-- comment_like +alter table comment_like rename column user_id to person_id; +alter index idx_comment_like_user rename to idx_comment_like_person; +alter table comment_like rename constraint comment_like_comment_id_user_id_key to comment_like_comment_id_person_id_key; +alter table comment_like rename constraint comment_like_user_id_fkey to comment_like_person_id_fkey; + +-- comment_saved +alter table comment_saved rename column user_id to person_id; +alter table comment_saved rename constraint comment_saved_comment_id_user_id_key to comment_saved_comment_id_person_id_key; +alter table comment_saved rename constraint comment_saved_user_id_fkey to comment_saved_person_id_fkey; + +-- community_follower +alter table community_follower rename column user_id to person_id; +alter table community_follower rename constraint community_follower_community_id_user_id_key to community_follower_community_id_person_id_key; +alter table community_follower rename constraint community_follower_user_id_fkey to community_follower_person_id_fkey; + +-- community_moderator +alter table community_moderator rename column user_id to person_id; +alter table community_moderator rename constraint community_moderator_community_id_user_id_key to community_moderator_community_id_person_id_key; +alter table community_moderator rename constraint community_moderator_user_id_fkey to community_moderator_person_id_fkey; + +-- community_user_ban +alter table community_user_ban rename to community_person_ban; +alter sequence community_user_ban_id_seq rename to community_person_ban_id_seq; +alter table community_person_ban rename column user_id to person_id; +alter table community_person_ban rename constraint community_user_ban_pkey to community_person_ban_pkey; +alter table community_person_ban rename constraint community_user_ban_community_id_fkey to community_person_ban_community_id_fkey; +alter table community_person_ban rename constraint community_user_ban_community_id_user_id_key to community_person_ban_community_id_person_id_key; +alter table community_person_ban rename constraint community_user_ban_user_id_fkey to community_person_ban_person_id_fkey; + +-- mod_add +alter table mod_add rename column mod_user_id to mod_person_id; +alter table mod_add rename column other_user_id to other_person_id; +alter table mod_add rename constraint mod_add_mod_user_id_fkey to mod_add_mod_person_id_fkey; +alter table mod_add rename constraint mod_add_other_user_id_fkey to mod_add_other_person_id_fkey; + +-- mod_add_community +alter table mod_add_community rename column mod_user_id to mod_person_id; +alter table mod_add_community rename column other_user_id to other_person_id; +alter table mod_add_community rename constraint mod_add_community_mod_user_id_fkey to mod_add_community_mod_person_id_fkey; +alter table mod_add_community rename constraint mod_add_community_other_user_id_fkey to mod_add_community_other_person_id_fkey; + +-- mod_ban +alter table mod_ban rename column mod_user_id to mod_person_id; +alter table mod_ban rename column other_user_id to other_person_id; +alter table mod_ban rename constraint mod_ban_mod_user_id_fkey to mod_ban_mod_person_id_fkey; +alter table mod_ban rename constraint mod_ban_other_user_id_fkey to mod_ban_other_person_id_fkey; + +-- mod_ban_community +alter table mod_ban_from_community rename column mod_user_id to mod_person_id; +alter table mod_ban_from_community rename column other_user_id to other_person_id; +alter table mod_ban_from_community rename constraint mod_ban_from_community_mod_user_id_fkey to mod_ban_from_community_mod_person_id_fkey; +alter table mod_ban_from_community rename constraint mod_ban_from_community_other_user_id_fkey to mod_ban_from_community_other_person_id_fkey; + +-- mod_lock_post +alter table mod_lock_post rename column mod_user_id to mod_person_id; +alter table mod_lock_post rename constraint mod_lock_post_mod_user_id_fkey to mod_lock_post_mod_person_id_fkey; + +-- mod_remove_comment +alter table mod_remove_comment rename column mod_user_id to mod_person_id; +alter table mod_remove_comment rename constraint mod_remove_comment_mod_user_id_fkey to mod_remove_comment_mod_person_id_fkey; + +-- mod_remove_community +alter table mod_remove_community rename column mod_user_id to mod_person_id; +alter table mod_remove_community rename constraint mod_remove_community_mod_user_id_fkey to mod_remove_community_mod_person_id_fkey; + +-- mod_remove_post +alter table mod_remove_post rename column mod_user_id to mod_person_id; +alter table mod_remove_post rename constraint mod_remove_post_mod_user_id_fkey to mod_remove_post_mod_person_id_fkey; + +-- mod_sticky_post +alter table mod_sticky_post rename column mod_user_id to mod_person_id; +alter table mod_sticky_post rename constraint mod_sticky_post_mod_user_id_fkey to mod_sticky_post_mod_person_id_fkey; + +-- password_reset_request +delete from password_reset_request; +alter table password_reset_request drop column user_id; +alter table password_reset_request add column local_user_id integer not null references local_user(id) on update cascade on delete cascade; + +-- post_like +alter table post_like rename column user_id to person_id; +alter index idx_post_like_user rename to idx_post_like_person; +alter table post_like rename constraint post_like_post_id_user_id_key to post_like_post_id_person_id_key; +alter table post_like rename constraint post_like_user_id_fkey to post_like_person_id_fkey; + +-- post_read +alter table post_read rename column user_id to person_id; +alter table post_read rename constraint post_read_post_id_user_id_key to post_read_post_id_person_id_key; +alter table post_read rename constraint post_read_user_id_fkey to post_read_person_id_fkey; + +-- post_saved +alter table post_saved rename column user_id to person_id; +alter table post_saved rename constraint post_saved_post_id_user_id_key to post_saved_post_id_person_id_key; +alter table post_saved rename constraint post_saved_user_id_fkey to post_saved_person_id_fkey; + +-- redo site aggregates trigger +create or replace function site_aggregates_activity(i text) returns integer + language plpgsql + as $$ +declare + count_ integer; +begin + select count(*) + into count_ + from ( + select c.creator_id from comment c + inner join person u on c.creator_id = u.id + where c.published > ('now'::timestamp - i::interval) + and u.local = true + union + select p.creator_id from post p + inner join person u on p.creator_id = u.id + where p.published > ('now'::timestamp - i::interval) + and u.local = true + ) a; + return count_; +end; +$$; diff --git a/scripts/clear_db.sh b/scripts/clear_db.sh new file mode 100755 index 000000000..b62490e12 --- /dev/null +++ b/scripts/clear_db.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public; DROP SCHEMA utils CASCADE;" diff --git a/scripts/restore_db.sh b/scripts/restore_db.sh new file mode 100755 index 000000000..318b99099 --- /dev/null +++ b/scripts/restore_db.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +psql -U lemmy -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;" +cat docker/dev/lemmy_dump_2021-01-29_16_13_40.sqldump | psql -U lemmy +psql -U lemmy -c "alter user lemmy with password 'password'" diff --git a/src/code_migrations.rs b/src/code_migrations.rs index f3bc3df53..bd67fe699 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -19,9 +19,9 @@ use lemmy_db_schema::{ source::{ comment::Comment, community::{Community, CommunityForm}, + person::{Person, PersonForm}, post::Post, private_message::PrivateMessage, - user::{UserForm, User_}, }, }; use lemmy_utils::{apub::generate_actor_keypair, settings::structs::Settings, LemmyError}; @@ -40,52 +40,42 @@ pub fn run_advanced_migrations(conn: &PgConnection) -> Result<(), LemmyError> { } fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> { - use lemmy_db_schema::schema::user_::dsl::*; + use lemmy_db_schema::schema::person::dsl::*; info!("Running user_updates_2020_04_02"); // Update the actor_id, private_key, and public_key, last_refreshed_at - let incorrect_users = user_ + let incorrect_persons = person .filter(actor_id.like("http://changeme_%")) .filter(local.eq(true)) - .load::(conn)?; + .load::(conn)?; - for cuser in &incorrect_users { + for cperson in &incorrect_persons { let keypair = generate_actor_keypair()?; - let form = UserForm { - name: cuser.name.to_owned(), - email: Some(cuser.email.to_owned()), - matrix_user_id: Some(cuser.matrix_user_id.to_owned()), - avatar: Some(cuser.avatar.to_owned()), - banner: Some(cuser.banner.to_owned()), - password_encrypted: cuser.password_encrypted.to_owned(), - preferred_username: Some(cuser.preferred_username.to_owned()), - published: Some(cuser.published), + let form = PersonForm { + name: cperson.name.to_owned(), + avatar: None, + banner: None, + preferred_username: None, + published: None, updated: None, - admin: cuser.admin, - banned: Some(cuser.banned), - show_nsfw: cuser.show_nsfw, - theme: cuser.theme.to_owned(), - default_sort_type: cuser.default_sort_type, - default_listing_type: cuser.default_listing_type, - lang: cuser.lang.to_owned(), - show_avatars: cuser.show_avatars, - send_notifications_to_email: cuser.send_notifications_to_email, - actor_id: Some(generate_apub_endpoint(EndpointType::User, &cuser.name)?), - bio: Some(cuser.bio.to_owned()), - local: cuser.local, - private_key: Some(keypair.private_key), - public_key: Some(keypair.public_key), + banned: None, + deleted: None, + actor_id: Some(generate_apub_endpoint(EndpointType::Person, &cperson.name)?), + bio: None, + local: None, + private_key: Some(Some(keypair.private_key)), + public_key: Some(Some(keypair.public_key)), last_refreshed_at: Some(naive_now()), inbox_url: None, shared_inbox_url: None, }; - User_::update(&conn, cuser.id, &form)?; + Person::update(&conn, cperson.id, &form)?; } - info!("{} user rows updated.", incorrect_users.len()); + info!("{} person rows updated.", incorrect_persons.len()); Ok(()) } @@ -231,20 +221,20 @@ fn post_thumbnail_url_updates_2020_07_27(conn: &PgConnection) -> Result<(), Lemm fn apub_columns_2021_02_02(conn: &PgConnection) -> Result<(), LemmyError> { info!("Running apub_columns_2021_02_02"); { - use lemmy_db_schema::schema::user_::dsl::*; - let users = user_ + use lemmy_db_schema::schema::person::dsl::*; + let persons = person .filter(inbox_url.like("http://changeme_%")) - .load::(conn)?; + .load::(conn)?; - for u in &users { - let inbox_url_ = generate_inbox_url(&u.actor_id)?; - let shared_inbox_url_ = generate_shared_inbox_url(&u.actor_id)?; - diesel::update(user_.find(u.id)) + for p in &persons { + let inbox_url_ = generate_inbox_url(&p.actor_id)?; + let shared_inbox_url_ = generate_shared_inbox_url(&p.actor_id)?; + diesel::update(person.find(p.id)) .set(( inbox_url.eq(inbox_url_), shared_inbox_url.eq(shared_inbox_url_), )) - .get_result::(conn)?; + .get_result::(conn)?; } }