* Tag posts and comments with language (fixes #440) * Untangle PostView tests * Implement test for PostView language query * Store languages directly in database * finish moving languages into db, it compiles * update post_view * serde skip Language.id field * add local_user_language table, other changes suggested in review * add code for local_user_discussion_language_view * Remove unnecessary clones in db view converteres * Fixing up some table and join issues. * Clearing the current languages. * Fix formatting. * update user languages in single transaction * proper test for user language queries * Some fixes for all / missing user languages. (#2404) * Some fixes for all / missing user languages. * Adding back in transaction. * fix test Co-authored-by: Dessalines <tyhou13@gmx.com> Co-authored-by: Dessalines <dessalines@users.noreply.github.com>
This commit is contained in:
parent
c89006c94a
commit
e4a49b6eab
41 changed files with 1016 additions and 323 deletions
276
Cargo.lock
generated
276
Cargo.lock
generated
|
@ -38,9 +38,9 @@ version = "0.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07520b54fc0f22ad30b90399b2a2689c6e5c113df0642ca3fa2f7ee823e54126"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -135,8 +135,8 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
|
||||
dependencies = [
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -286,9 +286,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "7525bedf54704abb1d469e88d7e7e9226df73778798a69cea5022d53b2ae91bc"
|
||||
dependencies = [
|
||||
"actix-router",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -297,9 +297,9 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -345,9 +345,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.57"
|
||||
version = "1.0.58"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc"
|
||||
checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
|
@ -390,9 +390,9 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -401,9 +401,9 @@ version = "0.1.56"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -860,10 +860,10 @@ checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
|
|||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"strsim",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -874,10 +874,10 @@ checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
|
|||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"strsim",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -888,10 +888,10 @@ checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f"
|
|||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"strsim",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -901,8 +901,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
|
||||
dependencies = [
|
||||
"darling_core 0.12.4",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -912,8 +912,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
|
||||
dependencies = [
|
||||
"darling_core 0.13.4",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -923,8 +923,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
|
||||
dependencies = [
|
||||
"darling_core 0.14.1",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -961,9 +961,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
|
||||
dependencies = [
|
||||
"darling 0.12.4",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -973,9 +973,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4"
|
||||
dependencies = [
|
||||
"darling 0.14.1",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -985,7 +985,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
|
||||
dependencies = [
|
||||
"derive_builder_core 0.10.2",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -995,7 +995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68"
|
||||
dependencies = [
|
||||
"derive_builder_core 0.11.2",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1005,10 +1005,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"rustc_version",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1053,9 +1053,9 @@ version = "1.4.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1145,9 +1145,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "6430bef5fcbfa22f3c431f05a14254d45f41ab634cabe09fad82e98d4f9fdc8b"
|
||||
dependencies = [
|
||||
"darling 0.13.4",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1158,9 +1158,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
|||
|
||||
[[package]]
|
||||
name = "email-encoding"
|
||||
version = "0.1.1"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b91dddc343e7eaa27f9764e5bffe57370d957017fdd75244f5045e829a8441"
|
||||
checksum = "827e1fb86d24d558ab0454ca3fa084f8a6144ade1e3e6982f697c586bf96b41b"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"memchr",
|
||||
|
@ -1406,9 +1406,9 @@ version = "0.3.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1598,9 +1598,9 @@ dependencies = [
|
|||
"log",
|
||||
"mac",
|
||||
"markup5ever",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2341,9 +2341,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||
dependencies = [
|
||||
"migrations_internals",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2582,9 +2582,9 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2758,9 +2758,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
|||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2856,9 +2856,9 @@ version = "1.0.10"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2919,9 +2919,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -2931,8 +2931,8 @@ version = "1.0.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -2947,9 +2947,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.39"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
|
||||
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
@ -2992,9 +2992,9 @@ checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3037,11 +3037,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
|
||||
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"proc-macro2 1.0.40",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3336,8 +3336,8 @@ checksum = "6f697b8b3f19bee20f30dc87213d05ce091c43bc733ab1bfc98b0e5cdd9943f3"
|
|||
dependencies = [
|
||||
"convert_case",
|
||||
"lazy_static",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"regex",
|
||||
"tinyjson",
|
||||
]
|
||||
|
@ -3492,9 +3492,9 @@ version = "1.0.137"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3538,9 +3538,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082"
|
||||
dependencies = [
|
||||
"darling 0.13.4",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3561,10 +3561,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"rustversion",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3661,9 +3661,9 @@ version = "0.6.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3710,8 +3710,8 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
|
|||
dependencies = [
|
||||
"phf_generator 0.10.0",
|
||||
"phf_shared 0.10.0",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3733,10 +3733,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef"
|
||||
dependencies = [
|
||||
"heck 0.4.0",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"rustversion",
|
||||
"syn 1.0.96",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3752,12 +3752,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.96"
|
||||
version = "1.0.98"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
|
||||
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
|
@ -3816,9 +3816,9 @@ version = "1.0.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3884,9 +3884,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.18.2"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395"
|
||||
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
|
@ -3919,9 +3919,9 @@ version = "1.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4021,10 +4021,10 @@ version = "0.6.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9403f1bafde247186684b230dc6f38b5cd514584e8bec1dd32514be4745fa757"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"proc-macro2 1.0.40",
|
||||
"prost-build",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4061,9 +4061,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.34"
|
||||
version = "0.1.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09"
|
||||
checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
|
@ -4091,18 +4091,18 @@ version = "0.1.20"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.23"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
|
||||
checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"once_cell",
|
||||
"valuable",
|
||||
]
|
||||
|
||||
|
@ -4209,9 +4209,9 @@ version = "0.10.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4249,9 +4249,9 @@ checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
|
||||
checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
|
@ -4397,9 +4397,9 @@ dependencies = [
|
|||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
|
@ -4421,7 +4421,7 @@ version = "0.2.79"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
||||
dependencies = [
|
||||
"quote 1.0.18",
|
||||
"quote 1.0.20",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
|
@ -4431,9 +4431,9 @@ version = "0.2.79"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.39",
|
||||
"quote 1.0.18",
|
||||
"syn 1.0.96",
|
||||
"proc-macro2 1.0.40",
|
||||
"quote 1.0.20",
|
||||
"syn 1.0.98",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
|
|
@ -7,6 +7,7 @@ use lemmy_api_common::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
local_user::{LocalUser, LocalUserForm},
|
||||
local_user_language::LocalUserLanguage,
|
||||
person::{Person, PersonForm},
|
||||
site::Site,
|
||||
},
|
||||
|
@ -118,6 +119,20 @@ impl Perform for SaveUserSettings {
|
|||
.await?
|
||||
.map_err(|e| LemmyError::from_error_message(e, "user_already_exists"))?;
|
||||
|
||||
if let Some(discussion_languages) = data.discussion_languages.clone() {
|
||||
// An empty array is a "clear" / set all languages
|
||||
let languages = if discussion_languages.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(discussion_languages)
|
||||
};
|
||||
|
||||
blocking(context.pool(), move |conn| {
|
||||
LocalUserLanguage::update_user_languages(conn, languages, local_user_id)
|
||||
})
|
||||
.await??;
|
||||
}
|
||||
|
||||
let local_user_form = LocalUserForm {
|
||||
person_id: Some(person_id),
|
||||
email,
|
||||
|
@ -128,7 +143,7 @@ impl Perform for SaveUserSettings {
|
|||
theme: data.theme.to_owned(),
|
||||
default_sort_type,
|
||||
default_listing_type,
|
||||
lang: data.lang.to_owned(),
|
||||
interface_language: data.interface_language.to_owned(),
|
||||
show_avatars: data.show_avatars,
|
||||
show_read_posts: data.show_read_posts,
|
||||
show_new_post_notifs: data.show_new_post_notifs,
|
||||
|
|
|
@ -6,6 +6,7 @@ use lemmy_api_common::{
|
|||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
language::Language,
|
||||
moderator::{ModAdd, ModAddForm},
|
||||
person::Person,
|
||||
},
|
||||
|
@ -59,6 +60,8 @@ impl Perform for LeaveAdmin {
|
|||
|
||||
let federated_instances = build_federated_instances(context.pool(), context.settings()).await?;
|
||||
|
||||
let all_languages = blocking(context.pool(), Language::read_all).await??;
|
||||
|
||||
Ok(GetSiteResponse {
|
||||
site_view: Some(site_view),
|
||||
admins,
|
||||
|
@ -66,6 +69,7 @@ impl Perform for LeaveAdmin {
|
|||
version: version::VERSION.to_string(),
|
||||
my_user: None,
|
||||
federated_instances,
|
||||
all_languages,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,15 +34,11 @@ impl Perform for Search {
|
|||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
|
||||
let show_bot_accounts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_bot_accounts);
|
||||
let show_read_posts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_read_posts);
|
||||
|
||||
let person_id = local_user_view.map(|u| u.person.id);
|
||||
let person_id = local_user_view.as_ref().map(|u| u.person.id);
|
||||
|
||||
let mut posts = Vec::new();
|
||||
let mut comments = Vec::new();
|
||||
|
@ -73,9 +69,6 @@ impl Perform for Search {
|
|||
PostQuery::builder()
|
||||
.conn(conn)
|
||||
.sort(sort)
|
||||
.show_nsfw(show_nsfw)
|
||||
.show_bot_accounts(show_bot_accounts)
|
||||
.show_read_posts(show_read_posts)
|
||||
.listing_type(listing_type)
|
||||
.community_id(community_id)
|
||||
.community_actor_id(community_actor_id)
|
||||
|
@ -146,9 +139,6 @@ impl Perform for Search {
|
|||
PostQuery::builder()
|
||||
.conn(conn)
|
||||
.sort(sort)
|
||||
.show_nsfw(show_nsfw)
|
||||
.show_bot_accounts(show_bot_accounts)
|
||||
.show_read_posts(show_read_posts)
|
||||
.listing_type(listing_type)
|
||||
.community_id(community_id)
|
||||
.community_actor_id(community_actor_id_2)
|
||||
|
@ -226,11 +216,7 @@ impl Perform for Search {
|
|||
PostQuery::builder()
|
||||
.conn(conn)
|
||||
.sort(sort)
|
||||
.show_nsfw(show_nsfw)
|
||||
.show_bot_accounts(show_bot_accounts)
|
||||
.show_read_posts(show_read_posts)
|
||||
.listing_type(listing_type)
|
||||
.my_person_id(person_id)
|
||||
.community_id(community_id)
|
||||
.community_actor_id(community_actor_id)
|
||||
.creator_id(creator_id)
|
||||
|
|
|
@ -14,7 +14,14 @@ pub struct Login {
|
|||
pub password: Sensitive<String>,
|
||||
}
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommentReplyId, CommunityId, PersonId, PersonMentionId, PrivateMessageId},
|
||||
newtypes::{
|
||||
CommentReplyId,
|
||||
CommunityId,
|
||||
LanguageId,
|
||||
PersonId,
|
||||
PersonMentionId,
|
||||
PrivateMessageId,
|
||||
},
|
||||
CommentSortType,
|
||||
SortType,
|
||||
};
|
||||
|
@ -56,7 +63,7 @@ pub struct SaveUserSettings {
|
|||
pub theme: Option<String>,
|
||||
pub default_sort_type: Option<i16>,
|
||||
pub default_listing_type: Option<i16>,
|
||||
pub lang: Option<String>,
|
||||
pub interface_language: Option<String>,
|
||||
pub avatar: Option<String>,
|
||||
pub banner: Option<String>,
|
||||
pub display_name: Option<String>,
|
||||
|
@ -69,6 +76,7 @@ pub struct SaveUserSettings {
|
|||
pub show_bot_accounts: Option<bool>,
|
||||
pub show_read_posts: Option<bool>,
|
||||
pub show_new_post_notifs: Option<bool>,
|
||||
pub discussion_languages: Option<Vec<LanguageId>>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::sensitive::Sensitive;
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommentId, CommunityId, DbUrl, PostId, PostReportId},
|
||||
newtypes::{CommentId, CommunityId, DbUrl, LanguageId, PostId, PostReportId},
|
||||
ListingType,
|
||||
SortType,
|
||||
};
|
||||
|
@ -17,6 +17,7 @@ pub struct CreatePost {
|
|||
pub body: Option<String>,
|
||||
pub honeypot: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub language_id: Option<LanguageId>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
|
@ -71,6 +72,7 @@ pub struct EditPost {
|
|||
pub url: Option<Url>,
|
||||
pub body: Option<String>,
|
||||
pub nsfw: Option<bool>,
|
||||
pub language_id: Option<LanguageId>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::sensitive::Sensitive;
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommentId, CommunityId, PersonId, PostId},
|
||||
source::language::Language,
|
||||
ListingType,
|
||||
ModlogActionType,
|
||||
SearchType,
|
||||
|
@ -168,6 +169,7 @@ pub struct GetSiteResponse {
|
|||
pub version: String,
|
||||
pub my_user: Option<MyUserInfo>,
|
||||
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
|
||||
pub all_languages: Vec<Language>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
@ -177,6 +179,7 @@ pub struct MyUserInfo {
|
|||
pub moderates: Vec<CommunityModeratorView>,
|
||||
pub community_blocks: Vec<CommunityBlockView>,
|
||||
pub person_blocks: Vec<PersonBlockView>,
|
||||
pub discussion_languages: Vec<Language>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
|
|
|
@ -47,16 +47,14 @@ where
|
|||
{
|
||||
let pool = pool.clone();
|
||||
let blocking_span = tracing::info_span!("blocking operation");
|
||||
let res = actix_web::web::block(move || {
|
||||
actix_web::web::block(move || {
|
||||
let entered = blocking_span.enter();
|
||||
let conn = pool.get()?;
|
||||
let res = (f)(&conn);
|
||||
drop(entered);
|
||||
Ok(res) as Result<T, LemmyError>
|
||||
})
|
||||
.await?;
|
||||
|
||||
res
|
||||
.await?
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
|
@ -407,7 +405,7 @@ pub async fn send_password_reset_email(
|
|||
.await??;
|
||||
|
||||
let email = &user.local_user.email.to_owned().expect("email");
|
||||
let lang = get_user_lang(user);
|
||||
let lang = get_interface_language(user);
|
||||
let subject = &lang.password_reset_subject(&user.person.name);
|
||||
let protocol_and_hostname = settings.get_protocol_and_hostname();
|
||||
let reset_link = format!("{}/password_change/{}", protocol_and_hostname, &token);
|
||||
|
@ -434,7 +432,7 @@ pub async fn send_verification_email(
|
|||
);
|
||||
blocking(pool, move |conn| EmailVerification::create(conn, &form)).await??;
|
||||
|
||||
let lang = get_user_lang(user);
|
||||
let lang = get_interface_language(user);
|
||||
let subject = lang.verify_email_subject(&settings.hostname);
|
||||
let body = lang.verify_email_body(&settings.hostname, &user.person.name, verify_link);
|
||||
send_email(&subject, new_email, &user.person.name, &body, settings)?;
|
||||
|
@ -447,14 +445,14 @@ pub fn send_email_verification_success(
|
|||
settings: &Settings,
|
||||
) -> Result<(), LemmyError> {
|
||||
let email = &user.local_user.email.to_owned().expect("email");
|
||||
let lang = get_user_lang(user);
|
||||
let lang = get_interface_language(user);
|
||||
let subject = &lang.email_verified_subject(&user.person.actor_id);
|
||||
let body = &lang.email_verified_body();
|
||||
send_email(subject, email, &user.person.name, body, settings)
|
||||
}
|
||||
|
||||
pub fn get_user_lang(user: &LocalUserView) -> Lang {
|
||||
let user_lang = LanguageId::new(user.local_user.lang.clone());
|
||||
pub fn get_interface_language(user: &LocalUserView) -> Lang {
|
||||
let user_lang = LanguageId::new(user.local_user.interface_language.clone());
|
||||
Lang::from_language_id(&user_lang).unwrap_or_else(|| {
|
||||
let en = LanguageId::new("en");
|
||||
Lang::from_language_id(&en).expect("default language")
|
||||
|
@ -466,7 +464,7 @@ pub fn send_application_approved_email(
|
|||
settings: &Settings,
|
||||
) -> Result<(), LemmyError> {
|
||||
let email = &user.local_user.email.to_owned().expect("email");
|
||||
let lang = get_user_lang(user);
|
||||
let lang = get_interface_language(user);
|
||||
let subject = lang.registration_approved_subject(&user.person.actor_id);
|
||||
let body = lang.registration_approved_body(&settings.hostname);
|
||||
send_email(&subject, email, &user.person.name, &body, settings)
|
||||
|
@ -488,7 +486,7 @@ pub async fn check_registration_application(
|
|||
})
|
||||
.await??;
|
||||
if let Some(deny_reason) = registration.deny_reason {
|
||||
let lang = get_user_lang(local_user_view);
|
||||
let lang = get_interface_language(local_user_view);
|
||||
let registration_denied_message = format!("{}: {}", lang.registration_denied(), &deny_reason);
|
||||
return Err(LemmyError::from_message(®istration_denied_message));
|
||||
} else {
|
||||
|
|
|
@ -21,6 +21,7 @@ use lemmy_apub::{
|
|||
use lemmy_db_schema::{
|
||||
source::{
|
||||
community::Community,
|
||||
language::Language,
|
||||
post::{Post, PostForm, PostLike, PostLikeForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
|
@ -90,6 +91,15 @@ impl PerformCrud for CreatePost {
|
|||
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
||||
.unwrap_or_default();
|
||||
|
||||
let language_id = Some(
|
||||
data.language_id.unwrap_or(
|
||||
blocking(context.pool(), move |conn| {
|
||||
Language::read_undetermined(conn)
|
||||
})
|
||||
.await??,
|
||||
),
|
||||
);
|
||||
|
||||
let post_form = PostForm {
|
||||
name: data.name.trim().to_owned(),
|
||||
url,
|
||||
|
@ -100,6 +110,7 @@ impl PerformCrud for CreatePost {
|
|||
embed_title,
|
||||
embed_description,
|
||||
embed_video_url,
|
||||
language_id,
|
||||
thumbnail_url: Some(thumbnail_url),
|
||||
..PostForm::default()
|
||||
};
|
||||
|
|
|
@ -32,15 +32,7 @@ impl PerformCrud for GetPosts {
|
|||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
let person_id = local_user_view.to_owned().map(|l| l.person.id);
|
||||
|
||||
let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
|
||||
let show_bot_accounts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_bot_accounts);
|
||||
let show_read_posts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_read_posts);
|
||||
let is_logged_in = local_user_view.is_some();
|
||||
|
||||
let sort = data.sort;
|
||||
let listing_type = listing_type_with_site_default(data.type_, context.pool()).await?;
|
||||
|
@ -63,13 +55,9 @@ impl PerformCrud for GetPosts {
|
|||
.conn(conn)
|
||||
.listing_type(Some(listing_type))
|
||||
.sort(sort)
|
||||
.show_nsfw(show_nsfw)
|
||||
.show_bot_accounts(show_bot_accounts)
|
||||
.show_read_posts(show_read_posts)
|
||||
.community_id(community_id)
|
||||
.community_actor_id(community_actor_id)
|
||||
.saved_only(saved_only)
|
||||
.my_person_id(person_id)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
|
@ -79,7 +67,7 @@ impl PerformCrud for GetPosts {
|
|||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_get_posts"))?;
|
||||
|
||||
// Blank out deleted or removed info for non-logged in users
|
||||
if person_id.is_none() {
|
||||
if !is_logged_in {
|
||||
for pv in posts
|
||||
.iter_mut()
|
||||
.filter(|p| p.post.deleted || p.post.removed)
|
||||
|
|
|
@ -14,7 +14,10 @@ use lemmy_apub::protocol::activities::{
|
|||
CreateOrUpdateType,
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::post::{Post, PostForm},
|
||||
source::{
|
||||
language::Language,
|
||||
post::{Post, PostForm},
|
||||
},
|
||||
traits::Crud,
|
||||
utils::{diesel_option_overwrite, naive_now},
|
||||
};
|
||||
|
@ -82,6 +85,15 @@ impl PerformCrud for EditPost {
|
|||
.map(|u| (Some(u.title), Some(u.description), Some(u.embed_video_url)))
|
||||
.unwrap_or_default();
|
||||
|
||||
let language_id = Some(
|
||||
data.language_id.unwrap_or(
|
||||
blocking(context.pool(), move |conn| {
|
||||
Language::read_undetermined(conn)
|
||||
})
|
||||
.await??,
|
||||
),
|
||||
);
|
||||
|
||||
let post_form = PostForm {
|
||||
creator_id: orig_post.creator_id.to_owned(),
|
||||
community_id: orig_post.community_id,
|
||||
|
@ -93,6 +105,7 @@ impl PerformCrud for EditPost {
|
|||
embed_title,
|
||||
embed_description,
|
||||
embed_video_url,
|
||||
language_id,
|
||||
thumbnail_url: Some(thumbnail_url),
|
||||
..PostForm::default()
|
||||
};
|
||||
|
|
|
@ -5,8 +5,8 @@ use lemmy_api_common::{
|
|||
utils::{
|
||||
blocking,
|
||||
check_person_block,
|
||||
get_interface_language,
|
||||
get_local_user_view_from_jwt,
|
||||
get_user_lang,
|
||||
send_email_to_user,
|
||||
},
|
||||
};
|
||||
|
@ -109,7 +109,7 @@ impl PerformCrud for CreatePrivateMessage {
|
|||
LocalUserView::read_person(conn, recipient_id)
|
||||
})
|
||||
.await??;
|
||||
let lang = get_user_lang(&local_recipient);
|
||||
let lang = get_interface_language(&local_recipient);
|
||||
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
|
||||
send_email_to_user(
|
||||
&local_recipient,
|
||||
|
|
|
@ -5,7 +5,8 @@ use lemmy_api_common::{
|
|||
site::{CreateSite, GetSite, GetSiteResponse, MyUserInfo},
|
||||
utils::{blocking, build_federated_instances, get_local_user_settings_view_from_jwt_opt},
|
||||
};
|
||||
use lemmy_db_views::structs::SiteView;
|
||||
use lemmy_db_schema::source::language::Language;
|
||||
use lemmy_db_views::structs::{LocalUserDiscussionLanguageView, SiteView};
|
||||
use lemmy_db_views_actor::structs::{
|
||||
CommunityBlockView,
|
||||
CommunityFollowerView,
|
||||
|
@ -83,6 +84,8 @@ impl PerformCrud for GetSite {
|
|||
.await?
|
||||
{
|
||||
let person_id = local_user_view.person.id;
|
||||
let local_user_id = local_user_view.local_user.id;
|
||||
|
||||
let follows = blocking(context.pool(), move |conn| {
|
||||
CommunityFollowerView::for_person(conn, person_id)
|
||||
})
|
||||
|
@ -109,12 +112,19 @@ impl PerformCrud for GetSite {
|
|||
.await?
|
||||
.map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
|
||||
|
||||
let discussion_languages = blocking(context.pool(), move |conn| {
|
||||
LocalUserDiscussionLanguageView::read_languages(conn, local_user_id)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| LemmyError::from_error_message(e, "system_err_login"))?;
|
||||
|
||||
Some(MyUserInfo {
|
||||
local_user_view,
|
||||
follows,
|
||||
moderates,
|
||||
community_blocks,
|
||||
person_blocks,
|
||||
discussion_languages,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
|
@ -122,6 +132,8 @@ impl PerformCrud for GetSite {
|
|||
|
||||
let federated_instances = build_federated_instances(context.pool(), context.settings()).await?;
|
||||
|
||||
let all_languages = blocking(context.pool(), Language::read_all).await??;
|
||||
|
||||
Ok(GetSiteResponse {
|
||||
site_view,
|
||||
admins,
|
||||
|
@ -129,6 +141,7 @@ impl PerformCrud for GetSite {
|
|||
version: version::VERSION.to_string(),
|
||||
my_user,
|
||||
federated_instances,
|
||||
all_languages,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ use lemmy_db_schema::{
|
|||
aggregates::structs::PersonAggregates,
|
||||
source::{
|
||||
local_user::{LocalUser, LocalUserForm},
|
||||
local_user_language::LocalUserLanguage,
|
||||
person::{Person, PersonForm},
|
||||
registration_application::{RegistrationApplication, RegistrationApplicationForm},
|
||||
site::Site,
|
||||
|
@ -167,10 +168,17 @@ impl PerformCrud for Register {
|
|||
}
|
||||
};
|
||||
|
||||
// Update the users languages to all by default
|
||||
let local_user_id = inserted_local_user.id;
|
||||
blocking(context.pool(), move |conn| {
|
||||
LocalUserLanguage::update_user_languages(conn, None, local_user_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
if require_application {
|
||||
// Create the registration application
|
||||
let form = RegistrationApplicationForm {
|
||||
local_user_id: Some(inserted_local_user.id),
|
||||
local_user_id: Some(local_user_id),
|
||||
// We already made sure answer was not null above
|
||||
answer: data.answer.to_owned(),
|
||||
..RegistrationApplicationForm::default()
|
||||
|
|
|
@ -34,13 +34,9 @@ impl PerformCrud for GetPersonDetails {
|
|||
|
||||
check_private_instance(&local_user_view, context.pool()).await?;
|
||||
|
||||
let show_nsfw = local_user_view.as_ref().map(|t| t.local_user.show_nsfw);
|
||||
let show_bot_accounts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_bot_accounts);
|
||||
let show_read_posts = local_user_view
|
||||
.as_ref()
|
||||
.map(|t| t.local_user.show_read_posts);
|
||||
|
||||
let person_details_id = match data.person_id {
|
||||
Some(id) => id,
|
||||
|
@ -58,8 +54,6 @@ impl PerformCrud for GetPersonDetails {
|
|||
}
|
||||
};
|
||||
|
||||
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 person_view = blocking(context.pool(), move |conn| {
|
||||
|
@ -77,15 +71,12 @@ impl PerformCrud for GetPersonDetails {
|
|||
let posts_query = PostQuery::builder()
|
||||
.conn(conn)
|
||||
.sort(sort)
|
||||
.show_nsfw(show_nsfw)
|
||||
.show_bot_accounts(show_bot_accounts)
|
||||
.show_read_posts(show_read_posts)
|
||||
.saved_only(saved_only)
|
||||
.community_id(community_id)
|
||||
.my_person_id(person_id)
|
||||
.page(page)
|
||||
.limit(limit);
|
||||
|
||||
let person_id = local_user_view.map(|uv| uv.person.id);
|
||||
let comments_query = CommentQuery::builder()
|
||||
.conn(conn)
|
||||
.my_person_id(person_id)
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
"commentsEnabled": true,
|
||||
"sensitive": false,
|
||||
"stickied": false,
|
||||
"language": {
|
||||
"identifier": "ko",
|
||||
"name": "한국어"
|
||||
},
|
||||
"published": "2021-10-29T15:10:51.557399+00:00"
|
||||
},
|
||||
"cc": [
|
||||
|
|
|
@ -27,5 +27,9 @@
|
|||
"sensitive": false,
|
||||
"commentsEnabled": true,
|
||||
"stickied": true,
|
||||
"language": {
|
||||
"identifier": "fr",
|
||||
"name": "Français"
|
||||
},
|
||||
"published": "2021-02-26T12:35:34.292626+00:00"
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ fn local_instance(context: &LemmyContext) -> &'static LocalInstance {
|
|||
.debug(context.settings().federation.debug)
|
||||
// TODO No idea why, but you can't pass context.settings() to the verify_url_function closure
|
||||
// without the value getting captured.
|
||||
.verify_url_function(|url| check_apub_id_valid(url, &SETTINGS.to_owned()))
|
||||
.verify_url_function(|url| check_apub_id_valid(url, &SETTINGS))
|
||||
.build()
|
||||
.expect("configure federation");
|
||||
LocalInstance::new(
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
local_instance,
|
||||
objects::{read_from_string_or_source_opt, verify_is_remote_object},
|
||||
protocol::{
|
||||
objects::page::{Attachment, AttributedTo, Page, PageType},
|
||||
objects::page::{Attachment, AttributedTo, LanguageTag, Page, PageType},
|
||||
ImageObject,
|
||||
Source,
|
||||
},
|
||||
|
@ -22,6 +22,7 @@ use lemmy_db_schema::{
|
|||
self,
|
||||
source::{
|
||||
community::Community,
|
||||
language::Language,
|
||||
moderator::{ModLockPost, ModLockPostForm, ModStickyPost, ModStickyPostForm},
|
||||
person::Person,
|
||||
post::{Post, PostForm},
|
||||
|
@ -98,6 +99,11 @@ impl ApubObject for ApubPost {
|
|||
Community::read(conn, community_id)
|
||||
})
|
||||
.await??;
|
||||
let language = self.language_id;
|
||||
let language = blocking(context.pool(), move |conn| {
|
||||
Language::read_from_id(conn, language)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let page = Page {
|
||||
kind: PageType::Page,
|
||||
|
@ -115,6 +121,7 @@ impl ApubObject for ApubPost {
|
|||
comments_enabled: Some(!self.locked),
|
||||
sensitive: Some(self.nsfw),
|
||||
stickied: Some(self.stickied),
|
||||
language: LanguageTag::new(language),
|
||||
published: Some(convert_datetime(self.published)),
|
||||
updated: self.updated.map(convert_datetime),
|
||||
};
|
||||
|
@ -181,6 +188,11 @@ impl ApubObject for ApubPost {
|
|||
let body_slurs_removed =
|
||||
read_from_string_or_source_opt(&page.content, &page.media_type, &page.source)
|
||||
.map(|s| Some(remove_slurs(&s, &context.settings().slur_regex())));
|
||||
let language = page.language.map(|l| l.identifier);
|
||||
let language = blocking(context.pool(), move |conn| {
|
||||
Language::read_id_from_code_opt(conn, language.as_deref())
|
||||
})
|
||||
.await??;
|
||||
|
||||
PostForm {
|
||||
name: page.name.clone(),
|
||||
|
@ -201,6 +213,7 @@ impl ApubObject for ApubPost {
|
|||
thumbnail_url: Some(thumbnail_url),
|
||||
ap_id: Some(page.id.clone().into()),
|
||||
local: Some(false),
|
||||
language_id: language,
|
||||
}
|
||||
} else {
|
||||
// if is mod action, only update locked/stickied fields, nothing else
|
||||
|
|
|
@ -16,7 +16,7 @@ use activitypub_federation::{
|
|||
use activitystreams_kinds::{link::LinkType, object::ImageType};
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use itertools::Itertools;
|
||||
use lemmy_db_schema::newtypes::DbUrl;
|
||||
use lemmy_db_schema::{newtypes::DbUrl, source::language::Language};
|
||||
use lemmy_utils::error::LemmyError;
|
||||
use lemmy_websocket::LemmyContext;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -62,8 +62,29 @@ pub struct Page {
|
|||
pub(crate) stickied: Option<bool>,
|
||||
pub(crate) published: Option<DateTime<FixedOffset>>,
|
||||
pub(crate) updated: Option<DateTime<FixedOffset>>,
|
||||
pub(crate) language: Option<LanguageTag>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct LanguageTag {
|
||||
pub(crate) identifier: String,
|
||||
pub(crate) name: String,
|
||||
}
|
||||
|
||||
impl LanguageTag {
|
||||
pub(crate) fn new(lang: Language) -> Option<LanguageTag> {
|
||||
// undetermined
|
||||
if lang.code == "und" {
|
||||
None
|
||||
} else {
|
||||
Some(LanguageTag {
|
||||
identifier: lang.code,
|
||||
name: lang.name,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub(crate) struct Link {
|
||||
|
|
54
crates/db_schema/src/impls/language.rs
Normal file
54
crates/db_schema/src/impls/language.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
use crate::{newtypes::LanguageId, source::language::Language};
|
||||
use diesel::{result::Error, PgConnection, RunQueryDsl, *};
|
||||
|
||||
impl Language {
|
||||
pub fn read_all(conn: &PgConnection) -> Result<Vec<Language>, Error> {
|
||||
use crate::schema::language::dsl::*;
|
||||
language.load::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn read_from_id(conn: &PgConnection, id_: LanguageId) -> Result<Language, Error> {
|
||||
use crate::schema::language::dsl::*;
|
||||
language.filter(id.eq(id_)).first::<Self>(conn)
|
||||
}
|
||||
|
||||
pub fn read_id_from_code(conn: &PgConnection, code_: &str) -> Result<LanguageId, Error> {
|
||||
use crate::schema::language::dsl::*;
|
||||
Ok(language.filter(code.eq(code_)).first::<Self>(conn)?.id)
|
||||
}
|
||||
|
||||
pub fn read_id_from_code_opt(
|
||||
conn: &PgConnection,
|
||||
code_: Option<&str>,
|
||||
) -> Result<Option<LanguageId>, Error> {
|
||||
if let Some(code_) = code_ {
|
||||
Ok(Some(Language::read_id_from_code(conn, code_)?))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_undetermined(conn: &PgConnection) -> Result<LanguageId, Error> {
|
||||
use crate::schema::language::dsl::*;
|
||||
Ok(language.filter(code.eq("und")).first::<Self>(conn)?.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{source::language::Language, utils::establish_unpooled_connection};
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_languages() {
|
||||
let conn = establish_unpooled_connection();
|
||||
|
||||
let all = Language::read_all(&conn).unwrap();
|
||||
|
||||
assert_eq!(184, all.len());
|
||||
assert_eq!("ak", all[5].code);
|
||||
assert_eq!("lv", all[99].code);
|
||||
assert_eq!("yi", all[179].code);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,7 @@ mod safe_settings_type {
|
|||
theme,
|
||||
default_sort_type,
|
||||
default_listing_type,
|
||||
lang,
|
||||
interface_language,
|
||||
show_avatars,
|
||||
send_notifications_to_email,
|
||||
validator_time,
|
||||
|
@ -48,7 +48,7 @@ mod safe_settings_type {
|
|||
theme,
|
||||
default_sort_type,
|
||||
default_listing_type,
|
||||
lang,
|
||||
interface_language,
|
||||
show_avatars,
|
||||
send_notifications_to_email,
|
||||
validator_time,
|
||||
|
|
42
crates/db_schema/src/impls/local_user_language.rs
Normal file
42
crates/db_schema/src/impls/local_user_language.rs
Normal file
|
@ -0,0 +1,42 @@
|
|||
use crate::{
|
||||
newtypes::{LanguageId, LocalUserId},
|
||||
source::{language::Language, local_user_language::*},
|
||||
};
|
||||
use diesel::{result::Error, PgConnection, RunQueryDsl, *};
|
||||
|
||||
impl LocalUserLanguage {
|
||||
/// Update the user's languages.
|
||||
///
|
||||
/// If no language_id vector is given, it will show all languages
|
||||
pub fn update_user_languages(
|
||||
conn: &PgConnection,
|
||||
language_ids: Option<Vec<LanguageId>>,
|
||||
for_local_user_id: LocalUserId,
|
||||
) -> Result<(), Error> {
|
||||
use crate::schema::local_user_language::dsl::*;
|
||||
|
||||
// If no language is given, read all languages
|
||||
let lang_ids = language_ids.unwrap_or(
|
||||
Language::read_all(conn)?
|
||||
.into_iter()
|
||||
.map(|l| l.id)
|
||||
.collect(),
|
||||
);
|
||||
|
||||
conn.build_transaction().read_write().run(|| {
|
||||
// Clear the current user languages
|
||||
delete(local_user_language.filter(local_user_id.eq(for_local_user_id))).execute(conn)?;
|
||||
|
||||
for l in lang_ids {
|
||||
let form = LocalUserLanguageForm {
|
||||
local_user_id: for_local_user_id,
|
||||
language_id: l,
|
||||
};
|
||||
insert_into(local_user_language)
|
||||
.values(form)
|
||||
.get_result::<Self>(conn)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
|
@ -5,7 +5,9 @@ pub mod comment_report;
|
|||
pub mod community;
|
||||
pub mod community_block;
|
||||
pub mod email_verification;
|
||||
pub mod language;
|
||||
pub mod local_user;
|
||||
pub mod local_user_language;
|
||||
pub mod moderator;
|
||||
pub mod password_reset_request;
|
||||
pub mod person;
|
||||
|
|
|
@ -387,6 +387,7 @@ mod tests {
|
|||
thumbnail_url: None,
|
||||
ap_id: inserted_post.ap_id.to_owned(),
|
||||
local: true,
|
||||
language_id: Default::default(),
|
||||
};
|
||||
|
||||
// Post Like
|
||||
|
|
|
@ -69,6 +69,14 @@ pub struct CommentReportId(i32);
|
|||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct PostReportId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct LanguageId(pub i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct LocalUserLanguageId(pub i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct CommentReplyId(i32);
|
||||
|
|
|
@ -156,7 +156,7 @@ table! {
|
|||
theme -> Varchar,
|
||||
default_sort_type -> Int2,
|
||||
default_listing_type -> Int2,
|
||||
lang -> Varchar,
|
||||
interface_language -> Varchar,
|
||||
show_avatars -> Bool,
|
||||
send_notifications_to_email -> Bool,
|
||||
validator_time -> Timestamp,
|
||||
|
@ -375,6 +375,7 @@ table! {
|
|||
thumbnail_url -> Nullable<Text>,
|
||||
ap_id -> Varchar,
|
||||
local -> Bool,
|
||||
language_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,6 +646,22 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
language (id) {
|
||||
id -> Int4,
|
||||
code -> Text,
|
||||
name -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
local_user_language(id) {
|
||||
id -> Int4,
|
||||
local_user_id -> Int4,
|
||||
language_id -> Int4,
|
||||
}
|
||||
}
|
||||
|
||||
joinable!(person_mention -> person_alias_1 (recipient_id));
|
||||
joinable!(comment_reply -> person_alias_1 (recipient_id));
|
||||
joinable!(post -> person_alias_1 (creator_id));
|
||||
|
@ -711,6 +728,9 @@ joinable!(registration_application -> local_user (local_user_id));
|
|||
joinable!(registration_application -> person (admin_id));
|
||||
joinable!(mod_hide_community -> person (mod_person_id));
|
||||
joinable!(mod_hide_community -> community (community_id));
|
||||
joinable!(post -> language (language_id));
|
||||
joinable!(local_user_language -> language (language_id));
|
||||
joinable!(local_user_language -> local_user (local_user_id));
|
||||
|
||||
joinable!(admin_purge_comment -> person (admin_person_id));
|
||||
joinable!(admin_purge_comment -> post (post_id));
|
||||
|
@ -767,5 +787,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
admin_purge_person,
|
||||
admin_purge_post,
|
||||
email_verification,
|
||||
registration_application
|
||||
registration_application,
|
||||
language,
|
||||
local_user_language
|
||||
);
|
||||
|
|
15
crates/db_schema/src/source/language.rs
Normal file
15
crates/db_schema/src/source/language.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
use crate::newtypes::LanguageId;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::language;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "full", derive(Queryable, Identifiable))]
|
||||
#[cfg_attr(feature = "full", table_name = "language")]
|
||||
pub struct Language {
|
||||
#[serde(skip)]
|
||||
pub id: LanguageId,
|
||||
pub code: String,
|
||||
pub name: String,
|
||||
}
|
|
@ -16,7 +16,7 @@ pub struct LocalUser {
|
|||
pub theme: String,
|
||||
pub default_sort_type: i16,
|
||||
pub default_listing_type: i16,
|
||||
pub lang: String,
|
||||
pub interface_language: String,
|
||||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub validator_time: chrono::NaiveDateTime,
|
||||
|
@ -40,7 +40,7 @@ pub struct LocalUserForm {
|
|||
pub theme: Option<String>,
|
||||
pub default_sort_type: Option<i16>,
|
||||
pub default_listing_type: Option<i16>,
|
||||
pub lang: Option<String>,
|
||||
pub interface_language: Option<String>,
|
||||
pub show_avatars: Option<bool>,
|
||||
pub send_notifications_to_email: Option<bool>,
|
||||
pub show_bot_accounts: Option<bool>,
|
||||
|
@ -63,7 +63,7 @@ pub struct LocalUserSettings {
|
|||
pub theme: String,
|
||||
pub default_sort_type: i16,
|
||||
pub default_listing_type: i16,
|
||||
pub lang: String,
|
||||
pub interface_language: String,
|
||||
pub show_avatars: bool,
|
||||
pub send_notifications_to_email: bool,
|
||||
pub validator_time: chrono::NaiveDateTime,
|
||||
|
|
23
crates/db_schema/src/source/local_user_language.rs
Normal file
23
crates/db_schema/src/source/local_user_language.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use crate::newtypes::{LanguageId, LocalUserId, LocalUserLanguageId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::local_user_language;
|
||||
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "full", derive(Queryable, Identifiable))]
|
||||
#[cfg_attr(feature = "full", table_name = "local_user_language")]
|
||||
pub struct LocalUserLanguage {
|
||||
#[serde(skip)]
|
||||
pub id: LocalUserLanguageId,
|
||||
pub local_user_id: LocalUserId,
|
||||
pub language_id: LanguageId,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", table_name = "local_user_language")]
|
||||
pub struct LocalUserLanguageForm {
|
||||
pub local_user_id: LocalUserId,
|
||||
pub language_id: LanguageId,
|
||||
}
|
|
@ -6,7 +6,9 @@ pub mod comment_report;
|
|||
pub mod community;
|
||||
pub mod community_block;
|
||||
pub mod email_verification;
|
||||
pub mod language;
|
||||
pub mod local_user;
|
||||
pub mod local_user_language;
|
||||
pub mod moderator;
|
||||
pub mod password_reset_request;
|
||||
pub mod person;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::newtypes::{CommunityId, DbUrl, PersonId, PostId};
|
||||
use crate::newtypes::{CommunityId, DbUrl, LanguageId, PersonId, PostId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
|
@ -27,6 +27,7 @@ pub struct Post {
|
|||
pub thumbnail_url: Option<DbUrl>,
|
||||
pub ap_id: DbUrl,
|
||||
pub local: bool,
|
||||
pub language_id: LanguageId,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -51,6 +52,7 @@ pub struct PostForm {
|
|||
pub thumbnail_url: Option<Option<DbUrl>>,
|
||||
pub ap_id: Option<DbUrl>,
|
||||
pub local: Option<bool>,
|
||||
pub language_id: Option<LanguageId>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
|
|
|
@ -574,6 +574,7 @@ mod tests {
|
|||
thumbnail_url: None,
|
||||
ap_id: inserted_post.ap_id.to_owned(),
|
||||
local: true,
|
||||
language_id: Default::default(),
|
||||
},
|
||||
community: CommunitySafe {
|
||||
id: inserted_community.id,
|
||||
|
|
|
@ -6,6 +6,8 @@ pub mod comment_report_view;
|
|||
#[cfg(feature = "full")]
|
||||
pub mod comment_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod local_user_discussion_language_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod local_user_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod post_report_view;
|
||||
|
|
32
crates/db_views/src/local_user_discussion_language_view.rs
Normal file
32
crates/db_views/src/local_user_discussion_language_view.rs
Normal file
|
@ -0,0 +1,32 @@
|
|||
use crate::structs::LocalUserDiscussionLanguageView;
|
||||
use diesel::{result::Error, ExpressionMethods, PgConnection, QueryDsl, RunQueryDsl};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::LocalUserId,
|
||||
schema::{language, local_user, local_user_language},
|
||||
source::{
|
||||
language::Language,
|
||||
local_user::{LocalUser, LocalUserSettings},
|
||||
},
|
||||
traits::ToSafeSettings,
|
||||
};
|
||||
|
||||
type LocalUserDiscussionLanguageViewTuple = (LocalUserSettings, Language);
|
||||
|
||||
impl LocalUserDiscussionLanguageView {
|
||||
pub fn read_languages(
|
||||
conn: &PgConnection,
|
||||
local_user_id: LocalUserId,
|
||||
) -> Result<Vec<Language>, Error> {
|
||||
let res = local_user_language::table
|
||||
.inner_join(local_user::table)
|
||||
.inner_join(language::table)
|
||||
.select((
|
||||
LocalUser::safe_settings_columns_tuple(),
|
||||
language::all_columns,
|
||||
))
|
||||
.filter(local_user::id.eq(local_user_id))
|
||||
.load::<LocalUserDiscussionLanguageViewTuple>(conn)?;
|
||||
|
||||
Ok(res.into_iter().map(|a| a.1).collect::<Vec<Language>>())
|
||||
}
|
||||
}
|
|
@ -2,12 +2,14 @@ use crate::structs::PostView;
|
|||
use diesel::{dsl::*, pg::Pg, result::Error, *};
|
||||
use lemmy_db_schema::{
|
||||
aggregates::structs::PostAggregates,
|
||||
newtypes::{CommunityId, DbUrl, PersonId, PostId},
|
||||
newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
|
||||
schema::{
|
||||
community,
|
||||
community_block,
|
||||
community_follower,
|
||||
community_person_ban,
|
||||
language,
|
||||
local_user_language,
|
||||
person,
|
||||
person_block,
|
||||
post,
|
||||
|
@ -18,6 +20,7 @@ use lemmy_db_schema::{
|
|||
},
|
||||
source::{
|
||||
community::{Community, CommunityFollower, CommunityPersonBan, CommunitySafe},
|
||||
language::Language,
|
||||
person::{Person, PersonSafe},
|
||||
person_block::PersonBlock,
|
||||
post::{Post, PostRead, PostSaved},
|
||||
|
@ -41,6 +44,7 @@ type PostViewTuple = (
|
|||
Option<PostRead>,
|
||||
Option<PersonBlock>,
|
||||
Option<i16>,
|
||||
Language,
|
||||
);
|
||||
|
||||
impl PostView {
|
||||
|
@ -51,7 +55,6 @@ impl PostView {
|
|||
) -> Result<Self, Error> {
|
||||
// The left join below will return None in this case
|
||||
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
|
||||
|
||||
let (
|
||||
post,
|
||||
creator,
|
||||
|
@ -63,6 +66,7 @@ impl PostView {
|
|||
read,
|
||||
creator_blocked,
|
||||
post_like,
|
||||
language,
|
||||
) = post::table
|
||||
.find(post_id)
|
||||
.inner_join(person::table)
|
||||
|
@ -115,6 +119,7 @@ impl PostView {
|
|||
.and(post_like::person_id.eq(person_id_join)),
|
||||
),
|
||||
)
|
||||
.inner_join(language::table)
|
||||
.select((
|
||||
post::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
|
@ -126,6 +131,7 @@ impl PostView {
|
|||
post_read::all_columns.nullable(),
|
||||
person_block::all_columns.nullable(),
|
||||
post_like::score.nullable(),
|
||||
language::all_columns,
|
||||
))
|
||||
.first::<PostViewTuple>(conn)?;
|
||||
|
||||
|
@ -148,6 +154,7 @@ impl PostView {
|
|||
read: read.is_some(),
|
||||
creator_blocked: creator_blocked.is_some(),
|
||||
my_vote,
|
||||
language,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +170,7 @@ pub struct PostQuery<'a> {
|
|||
community_id: Option<CommunityId>,
|
||||
community_actor_id: Option<DbUrl>,
|
||||
my_person_id: Option<PersonId>,
|
||||
my_local_user_id: Option<LocalUserId>,
|
||||
search_term: Option<String>,
|
||||
url_search: Option<String>,
|
||||
show_nsfw: Option<bool>,
|
||||
|
@ -179,6 +187,7 @@ impl<'a> PostQuery<'a> {
|
|||
|
||||
// The left join below will return None in this case
|
||||
let person_id_join = self.my_person_id.unwrap_or(PersonId(-1));
|
||||
let local_user_id_join = self.my_local_user_id.unwrap_or(LocalUserId(-1));
|
||||
|
||||
let mut query = post::table
|
||||
.inner_join(person::table)
|
||||
|
@ -238,6 +247,14 @@ impl<'a> PostQuery<'a> {
|
|||
.and(post_like::person_id.eq(person_id_join)),
|
||||
),
|
||||
)
|
||||
.inner_join(language::table)
|
||||
.left_join(
|
||||
local_user_language::table.on(
|
||||
post::language_id
|
||||
.eq(local_user_language::language_id)
|
||||
.and(local_user_language::local_user_id.eq(local_user_id_join)),
|
||||
),
|
||||
)
|
||||
.select((
|
||||
post::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
|
@ -249,6 +266,7 @@ impl<'a> PostQuery<'a> {
|
|||
post_read::all_columns.nullable(),
|
||||
person_block::all_columns.nullable(),
|
||||
post_like::score.nullable(),
|
||||
language::all_columns,
|
||||
))
|
||||
.into_boxed();
|
||||
|
||||
|
@ -323,6 +341,11 @@ impl<'a> PostQuery<'a> {
|
|||
query = query.filter(post_read::id.is_null());
|
||||
}
|
||||
|
||||
// Filter out the rows with missing languages
|
||||
if self.my_local_user_id.is_some() {
|
||||
query = query.filter(local_user_language::id.is_not_null());
|
||||
}
|
||||
|
||||
// Don't show blocked communities or persons
|
||||
if self.my_person_id.is_some() {
|
||||
query = query.filter(community_block::person_id.is_null());
|
||||
|
@ -403,6 +426,7 @@ impl ViewToVec for PostView {
|
|||
read: a.7.is_some(),
|
||||
creator_blocked: a.8.is_some(),
|
||||
my_vote: a.9,
|
||||
language: a.10,
|
||||
})
|
||||
.collect::<Vec<Self>>()
|
||||
}
|
||||
|
@ -411,11 +435,16 @@ impl ViewToVec for PostView {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::post_view::{PostQuery, PostView};
|
||||
use diesel::PgConnection;
|
||||
use lemmy_db_schema::{
|
||||
aggregates::structs::PostAggregates,
|
||||
newtypes::LanguageId,
|
||||
source::{
|
||||
community::*,
|
||||
community_block::{CommunityBlock, CommunityBlockForm},
|
||||
language::Language,
|
||||
local_user::{LocalUser, LocalUserForm},
|
||||
local_user_language::LocalUserLanguage,
|
||||
person::*,
|
||||
person_block::{PersonBlock, PersonBlockForm},
|
||||
post::*,
|
||||
|
@ -427,15 +456,16 @@ mod tests {
|
|||
};
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_crud() {
|
||||
let conn = establish_unpooled_connection();
|
||||
struct Data {
|
||||
inserted_person: Person,
|
||||
inserted_blocked_person: Person,
|
||||
inserted_bot: Person,
|
||||
inserted_community: Community,
|
||||
inserted_post: Post,
|
||||
}
|
||||
|
||||
fn init_data(conn: &PgConnection) -> Data {
|
||||
let person_name = "tegan".to_string();
|
||||
let community_name = "test_community_3".to_string();
|
||||
let post_name = "test post 3".to_string();
|
||||
let bot_post_name = "test bot post".to_string();
|
||||
|
||||
let new_person = PersonForm {
|
||||
name: person_name.to_owned(),
|
||||
|
@ -443,43 +473,44 @@ mod tests {
|
|||
..PersonForm::default()
|
||||
};
|
||||
|
||||
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||
let inserted_person = Person::create(conn, &new_person).unwrap();
|
||||
|
||||
let new_bot = PersonForm {
|
||||
name: person_name.to_owned(),
|
||||
name: "mybot".to_string(),
|
||||
bot_account: Some(true),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
|
||||
let inserted_bot = Person::create(&conn, &new_bot).unwrap();
|
||||
let inserted_bot = Person::create(conn, &new_bot).unwrap();
|
||||
|
||||
let new_community = CommunityForm {
|
||||
name: community_name.to_owned(),
|
||||
name: "test_community_3".to_string(),
|
||||
title: "nada".to_owned(),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..CommunityForm::default()
|
||||
};
|
||||
|
||||
let inserted_community = Community::create(&conn, &new_community).unwrap();
|
||||
let inserted_community = Community::create(conn, &new_community).unwrap();
|
||||
|
||||
// Test a person block, make sure the post query doesn't include their post
|
||||
let blocked_person = PersonForm {
|
||||
name: person_name.to_owned(),
|
||||
name: person_name,
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
|
||||
let inserted_blocked_person = Person::create(&conn, &blocked_person).unwrap();
|
||||
let inserted_blocked_person = Person::create(conn, &blocked_person).unwrap();
|
||||
|
||||
let post_from_blocked_person = PostForm {
|
||||
name: "blocked_person_post".to_string(),
|
||||
creator_id: inserted_blocked_person.id,
|
||||
community_id: inserted_community.id,
|
||||
language_id: Some(LanguageId(1)),
|
||||
..PostForm::default()
|
||||
};
|
||||
|
||||
Post::create(&conn, &post_from_blocked_person).unwrap();
|
||||
Post::create(conn, &post_from_blocked_person).unwrap();
|
||||
|
||||
// block that person
|
||||
let person_block = PersonBlockForm {
|
||||
|
@ -487,72 +518,58 @@ mod tests {
|
|||
target_id: inserted_blocked_person.id,
|
||||
};
|
||||
|
||||
PersonBlock::block(&conn, &person_block).unwrap();
|
||||
PersonBlock::block(conn, &person_block).unwrap();
|
||||
|
||||
// A sample post
|
||||
let new_post = PostForm {
|
||||
name: post_name.to_owned(),
|
||||
name: "test post 3".to_string(),
|
||||
creator_id: inserted_person.id,
|
||||
community_id: inserted_community.id,
|
||||
language_id: Some(LanguageId(47)),
|
||||
..PostForm::default()
|
||||
};
|
||||
|
||||
let inserted_post = Post::create(&conn, &new_post).unwrap();
|
||||
let inserted_post = Post::create(conn, &new_post).unwrap();
|
||||
|
||||
let new_bot_post = PostForm {
|
||||
name: bot_post_name,
|
||||
name: "test bot post".to_string(),
|
||||
creator_id: inserted_bot.id,
|
||||
community_id: inserted_community.id,
|
||||
..PostForm::default()
|
||||
};
|
||||
|
||||
let _inserted_bot_post = Post::create(&conn, &new_bot_post).unwrap();
|
||||
let _inserted_bot_post = Post::create(conn, &new_bot_post).unwrap();
|
||||
|
||||
let post_like_form = PostLikeForm {
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
Data {
|
||||
inserted_person,
|
||||
inserted_blocked_person,
|
||||
inserted_bot,
|
||||
inserted_community,
|
||||
inserted_post,
|
||||
}
|
||||
}
|
||||
|
||||
let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
|
||||
fn cleanup(data: Data, conn: &PgConnection) {
|
||||
let num_deleted = Post::delete(conn, data.inserted_post.id).unwrap();
|
||||
Community::delete(conn, data.inserted_community.id).unwrap();
|
||||
Person::delete(conn, data.inserted_person.id).unwrap();
|
||||
Person::delete(conn, data.inserted_bot.id).unwrap();
|
||||
Person::delete(conn, data.inserted_blocked_person.id).unwrap();
|
||||
assert_eq!(1, num_deleted);
|
||||
}
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
id: inserted_post_like.id,
|
||||
post_id: inserted_post.id,
|
||||
person_id: inserted_person.id,
|
||||
published: inserted_post_like.published,
|
||||
score: 1,
|
||||
};
|
||||
fn expected_post_listing(data: &Data, conn: &PgConnection) -> PostView {
|
||||
let (inserted_person, inserted_community, inserted_post) = (
|
||||
&data.inserted_person,
|
||||
&data.inserted_community,
|
||||
&data.inserted_post,
|
||||
);
|
||||
let agg = PostAggregates::read(conn, inserted_post.id).unwrap();
|
||||
|
||||
let read_post_listings_with_person = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.show_bot_accounts(Some(false))
|
||||
.community_id(Some(inserted_community.id))
|
||||
.my_person_id(Some(inserted_person.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
let read_post_listings_no_person = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.community_id(Some(inserted_community.id))
|
||||
.build()
|
||||
.list()
|
||||
.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 person version
|
||||
let expected_post_listing_no_person = PostView {
|
||||
PostView {
|
||||
post: Post {
|
||||
id: inserted_post.id,
|
||||
name: post_name,
|
||||
name: inserted_post.name.clone(),
|
||||
creator_id: inserted_person.id,
|
||||
url: None,
|
||||
body: None,
|
||||
|
@ -570,11 +587,12 @@ mod tests {
|
|||
thumbnail_url: None,
|
||||
ap_id: inserted_post.ap_id.to_owned(),
|
||||
local: true,
|
||||
language_id: LanguageId(47),
|
||||
},
|
||||
my_vote: None,
|
||||
creator: PersonSafe {
|
||||
id: inserted_person.id,
|
||||
name: person_name,
|
||||
name: inserted_person.name.clone(),
|
||||
display_name: None,
|
||||
published: inserted_person.published,
|
||||
avatar: None,
|
||||
|
@ -595,7 +613,7 @@ mod tests {
|
|||
creator_banned_from_community: false,
|
||||
community: CommunitySafe {
|
||||
id: inserted_community.id,
|
||||
name: community_name,
|
||||
name: inserted_community.name.clone(),
|
||||
icon: None,
|
||||
removed: false,
|
||||
deleted: false,
|
||||
|
@ -614,8 +632,8 @@ mod tests {
|
|||
id: agg.id,
|
||||
post_id: inserted_post.id,
|
||||
comments: 0,
|
||||
score: 1,
|
||||
upvotes: 1,
|
||||
score: 0,
|
||||
upvotes: 0,
|
||||
downvotes: 0,
|
||||
stickied: false,
|
||||
published: agg.published,
|
||||
|
@ -626,66 +644,239 @@ mod tests {
|
|||
read: false,
|
||||
saved: false,
|
||||
creator_blocked: false,
|
||||
};
|
||||
language: Language {
|
||||
id: LanguageId(47),
|
||||
code: "fr".to_string(),
|
||||
name: "Français".to_string(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn post_listing_with_person() {
|
||||
let conn = establish_unpooled_connection();
|
||||
let data = init_data(&conn);
|
||||
|
||||
let read_post_listing = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.community_id(Some(data.inserted_community.id))
|
||||
.show_bot_accounts(Some(false))
|
||||
.my_person_id(Some(data.inserted_person.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
let post_listing_single_with_person =
|
||||
PostView::read(&conn, data.inserted_post.id, Some(data.inserted_person.id)).unwrap();
|
||||
|
||||
let mut expected_post_listing_with_user = expected_post_listing(&data, &conn);
|
||||
|
||||
// Should be only one person, IE the bot post, and blocked should be missing
|
||||
assert_eq!(1, read_post_listing.len());
|
||||
|
||||
assert_eq!(expected_post_listing_with_user, read_post_listing[0]);
|
||||
expected_post_listing_with_user.my_vote = Some(0);
|
||||
assert_eq!(
|
||||
expected_post_listing_with_user,
|
||||
post_listing_single_with_person
|
||||
);
|
||||
|
||||
let post_listings_with_bots = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.community_id(Some(data.inserted_community.id))
|
||||
.show_bot_accounts(Some(true))
|
||||
.my_person_id(Some(data.inserted_person.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
// should include bot post which has "undetermined" language
|
||||
assert_eq!(2, post_listings_with_bots.len());
|
||||
|
||||
cleanup(data, &conn);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn post_listing_no_person() {
|
||||
let conn = establish_unpooled_connection();
|
||||
let data = init_data(&conn);
|
||||
|
||||
let read_post_listing_multiple_no_person = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.community_id(Some(data.inserted_community.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
let read_post_listing_single_no_person =
|
||||
PostView::read(&conn, data.inserted_post.id, None).unwrap();
|
||||
|
||||
let expected_post_listing_no_person = expected_post_listing(&data, &conn);
|
||||
|
||||
// Should be 2 posts, with the bot post, and the blocked
|
||||
assert_eq!(3, read_post_listing_multiple_no_person.len());
|
||||
|
||||
assert_eq!(
|
||||
expected_post_listing_no_person,
|
||||
read_post_listing_multiple_no_person[1]
|
||||
);
|
||||
assert_eq!(
|
||||
expected_post_listing_no_person,
|
||||
read_post_listing_single_no_person
|
||||
);
|
||||
|
||||
cleanup(data, &conn);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn post_listing_block_community() {
|
||||
let conn = establish_unpooled_connection();
|
||||
let data = init_data(&conn);
|
||||
|
||||
// Test a community block
|
||||
let community_block = CommunityBlockForm {
|
||||
person_id: inserted_person.id,
|
||||
community_id: inserted_community.id,
|
||||
person_id: data.inserted_person.id,
|
||||
community_id: data.inserted_community.id,
|
||||
};
|
||||
CommunityBlock::block(&conn, &community_block).unwrap();
|
||||
|
||||
let read_post_listings_with_person_after_block = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.show_bot_accounts(Some(false))
|
||||
.community_id(Some(inserted_community.id))
|
||||
.my_person_id(Some(inserted_person.id))
|
||||
.community_id(Some(data.inserted_community.id))
|
||||
.show_bot_accounts(Some(true))
|
||||
.my_person_id(Some(data.inserted_person.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
// Should be 0 posts after the community block
|
||||
assert_eq!(0, read_post_listings_with_person_after_block.len());
|
||||
|
||||
CommunityBlock::unblock(&conn, &community_block).unwrap();
|
||||
cleanup(data, &conn);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn post_listing_like() {
|
||||
let conn = establish_unpooled_connection();
|
||||
let data = init_data(&conn);
|
||||
|
||||
let post_like_form = PostLikeForm {
|
||||
post_id: data.inserted_post.id,
|
||||
person_id: data.inserted_person.id,
|
||||
score: 1,
|
||||
};
|
||||
|
||||
let inserted_post_like = PostLike::like(&conn, &post_like_form).unwrap();
|
||||
|
||||
let expected_post_like = PostLike {
|
||||
id: inserted_post_like.id,
|
||||
post_id: data.inserted_post.id,
|
||||
person_id: data.inserted_person.id,
|
||||
published: inserted_post_like.published,
|
||||
score: 1,
|
||||
};
|
||||
assert_eq!(expected_post_like, inserted_post_like);
|
||||
|
||||
let like_removed =
|
||||
PostLike::remove(&conn, data.inserted_person.id, data.inserted_post.id).unwrap();
|
||||
assert_eq!(1, like_removed);
|
||||
cleanup(data, &conn);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn post_listing_person_language() {
|
||||
let conn = establish_unpooled_connection();
|
||||
let data = init_data(&conn);
|
||||
|
||||
let spanish_id = Language::read_id_from_code(&conn, "es").unwrap();
|
||||
let post_spanish = PostForm {
|
||||
name: "asffgdsc".to_string(),
|
||||
creator_id: data.inserted_person.id,
|
||||
community_id: data.inserted_community.id,
|
||||
language_id: Some(spanish_id),
|
||||
..PostForm::default()
|
||||
};
|
||||
|
||||
Post::create(&conn, &post_spanish).unwrap();
|
||||
|
||||
let my_person_form = PersonForm {
|
||||
name: "Reverie Toiba".to_string(),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
let my_person = Person::create(&conn, &my_person_form).unwrap();
|
||||
let local_user_form = LocalUserForm {
|
||||
person_id: Some(my_person.id),
|
||||
password_encrypted: Some("".to_string()),
|
||||
..Default::default()
|
||||
};
|
||||
let local_user = LocalUser::create(&conn, &local_user_form).unwrap();
|
||||
|
||||
// Update the users languages to all
|
||||
LocalUserLanguage::update_user_languages(&conn, None, local_user.id).unwrap();
|
||||
|
||||
let post_listings_all = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.show_bot_accounts(Some(true))
|
||||
.my_person_id(Some(my_person.id))
|
||||
.my_local_user_id(Some(local_user.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
// TODO More needs to be added here
|
||||
let mut expected_post_listing_with_user = expected_post_listing_no_person.to_owned();
|
||||
expected_post_listing_with_user.my_vote = Some(1);
|
||||
// no language filters specified, all posts should be returned
|
||||
assert_eq!(4, post_listings_all.len());
|
||||
|
||||
let like_removed = PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
|
||||
let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
|
||||
PersonBlock::unblock(&conn, &person_block).unwrap();
|
||||
CommunityBlock::unblock(&conn, &community_block).unwrap();
|
||||
Community::delete(&conn, inserted_community.id).unwrap();
|
||||
Person::delete(&conn, inserted_person.id).unwrap();
|
||||
Person::delete(&conn, inserted_bot.id).unwrap();
|
||||
Person::delete(&conn, inserted_blocked_person.id).unwrap();
|
||||
let french_id = Language::read_id_from_code(&conn, "fr").unwrap();
|
||||
LocalUserLanguage::update_user_languages(&conn, Some(vec![french_id]), local_user.id).unwrap();
|
||||
|
||||
// The with user
|
||||
let post_listing_french = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.show_bot_accounts(Some(true))
|
||||
.my_person_id(Some(my_person.id))
|
||||
.my_local_user_id(Some(local_user.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
// only one french language post should be returned
|
||||
assert_eq!(1, post_listing_french.len());
|
||||
assert_eq!(french_id, post_listing_french[0].post.language_id);
|
||||
|
||||
let undetermined_id = Language::read_id_from_code(&conn, "und").unwrap();
|
||||
LocalUserLanguage::update_user_languages(
|
||||
&conn,
|
||||
Some(vec![french_id, undetermined_id]),
|
||||
local_user.id,
|
||||
)
|
||||
.unwrap();
|
||||
let post_listings_french_und = PostQuery::builder()
|
||||
.conn(&conn)
|
||||
.sort(Some(SortType::New))
|
||||
.show_bot_accounts(Some(true))
|
||||
.my_person_id(Some(my_person.id))
|
||||
.my_local_user_id(Some(local_user.id))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
|
||||
// french post and undetermined language post should be returned
|
||||
assert_eq!(2, post_listings_french_und.len());
|
||||
assert_eq!(
|
||||
expected_post_listing_with_user,
|
||||
read_post_listings_with_person[0]
|
||||
);
|
||||
assert_eq!(
|
||||
expected_post_listing_with_user,
|
||||
read_post_listing_with_person
|
||||
undetermined_id,
|
||||
post_listings_french_und[0].post.language_id
|
||||
);
|
||||
assert_eq!(french_id, post_listings_french_und[1].post.language_id);
|
||||
|
||||
// Should be only one person, IE the bot post, and blocked should be missing
|
||||
assert_eq!(1, read_post_listings_with_person.len());
|
||||
|
||||
// Without the user
|
||||
assert_eq!(
|
||||
expected_post_listing_no_person,
|
||||
read_post_listings_no_person[1]
|
||||
);
|
||||
assert_eq!(expected_post_listing_no_person, read_post_listing_no_person);
|
||||
|
||||
// Should be 2 posts, with the bot post, and the blocked
|
||||
assert_eq!(3, read_post_listings_no_person.len());
|
||||
|
||||
// Should be 0 posts after the community block
|
||||
assert_eq!(0, read_post_listings_with_person_after_block.len());
|
||||
|
||||
assert_eq!(expected_post_like, inserted_post_like);
|
||||
assert_eq!(1, like_removed);
|
||||
assert_eq!(1, num_deleted);
|
||||
cleanup(data, &conn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,7 +239,7 @@ mod tests {
|
|||
theme: inserted_sara_local_user.theme,
|
||||
default_sort_type: inserted_sara_local_user.default_sort_type,
|
||||
default_listing_type: inserted_sara_local_user.default_listing_type,
|
||||
lang: inserted_sara_local_user.lang,
|
||||
interface_language: inserted_sara_local_user.interface_language,
|
||||
show_avatars: inserted_sara_local_user.show_avatars,
|
||||
send_notifications_to_email: inserted_sara_local_user.send_notifications_to_email,
|
||||
validator_time: inserted_sara_local_user.validator_time,
|
||||
|
|
|
@ -4,6 +4,7 @@ use lemmy_db_schema::{
|
|||
comment::Comment,
|
||||
comment_report::CommentReport,
|
||||
community::CommunitySafe,
|
||||
language::Language,
|
||||
local_user::{LocalUser, LocalUserSettings},
|
||||
person::{Person, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
|
||||
post::Post,
|
||||
|
@ -83,6 +84,7 @@ pub struct PostView {
|
|||
pub read: bool, // Left join to PostRead
|
||||
pub creator_blocked: bool, // Left join to PersonBlock
|
||||
pub my_vote: Option<i16>, // Left join to PostLike
|
||||
pub language: Language,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
|
@ -105,3 +107,9 @@ pub struct SiteView {
|
|||
pub site: Site,
|
||||
pub counts: SiteAggregates,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct LocalUserDiscussionLanguageView {
|
||||
pub local_user: LocalUserSettings,
|
||||
pub language: Language,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use lemmy_api_common::{
|
|||
community::CommunityResponse,
|
||||
person::PrivateMessageResponse,
|
||||
post::PostResponse,
|
||||
utils::{blocking, check_person_block, get_user_lang, send_email_to_user},
|
||||
utils::{blocking, check_person_block, get_interface_language, send_email_to_user},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},
|
||||
|
@ -213,7 +213,7 @@ pub async fn send_local_notifs(
|
|||
|
||||
// Send an email to those local users that have notifications on
|
||||
if do_send_email {
|
||||
let lang = get_user_lang(&mention_user_view);
|
||||
let lang = get_interface_language(&mention_user_view);
|
||||
send_email_to_user(
|
||||
&mention_user_view,
|
||||
&lang.notification_mentioned_by_subject(&person.name),
|
||||
|
@ -263,7 +263,7 @@ pub async fn send_local_notifs(
|
|||
.ok();
|
||||
|
||||
if do_send_email {
|
||||
let lang = get_user_lang(&parent_user_view);
|
||||
let lang = get_interface_language(&parent_user_view);
|
||||
send_email_to_user(
|
||||
&parent_user_view,
|
||||
&lang.notification_comment_reply_subject(&person.name),
|
||||
|
@ -304,7 +304,7 @@ pub async fn send_local_notifs(
|
|||
.ok();
|
||||
|
||||
if do_send_email {
|
||||
let lang = get_user_lang(&parent_user_view);
|
||||
let lang = get_interface_language(&parent_user_view);
|
||||
send_email_to_user(
|
||||
&parent_user_view,
|
||||
&lang.notification_post_reply_subject(&person.name),
|
||||
|
|
6
migrations/2022-06-21-123144_language-tags/down.sql
Normal file
6
migrations/2022-06-21-123144_language-tags/down.sql
Normal file
|
@ -0,0 +1,6 @@
|
|||
alter table post drop column language_id;
|
||||
drop table local_user_language;
|
||||
drop table language;
|
||||
|
||||
alter table local_user rename column interface_language to lang;
|
||||
|
200
migrations/2022-06-21-123144_language-tags/up.sql
Normal file
200
migrations/2022-06-21-123144_language-tags/up.sql
Normal file
|
@ -0,0 +1,200 @@
|
|||
create table language (
|
||||
id serial primary key,
|
||||
code varchar(3),
|
||||
name text
|
||||
);
|
||||
create table local_user_language (
|
||||
id serial primary key,
|
||||
local_user_id int references local_user on update cascade on delete cascade not null,
|
||||
language_id int references language on update cascade on delete cascade not null,
|
||||
unique (local_user_id, language_id)
|
||||
);
|
||||
|
||||
alter table local_user rename column lang to interface_language;
|
||||
|
||||
alter table post add column language_id integer references language not null default 0;
|
||||
|
||||
insert into language(id, code, name) values (0, 'und', 'Undetermined');
|
||||
insert into language(code, name) values ('aa', 'Afaraf');
|
||||
insert into language(code, name) values ('ab', 'аҧсуа бызшәа');
|
||||
insert into language(code, name) values ('ae', 'avesta');
|
||||
insert into language(code, name) values ('af', 'Afrikaans');
|
||||
insert into language(code, name) values ('ak', 'Akan');
|
||||
insert into language(code, name) values ('am', 'አማርኛ');
|
||||
insert into language(code, name) values ('an', 'aragonés');
|
||||
insert into language(code, name) values ('ar', 'اَلْعَرَبِيَّةُ');
|
||||
insert into language(code, name) values ('as', 'অসমীয়া');
|
||||
insert into language(code, name) values ('av', 'авар мацӀ');
|
||||
insert into language(code, name) values ('ay', 'aymar aru');
|
||||
insert into language(code, name) values ('az', 'azərbaycan dili');
|
||||
insert into language(code, name) values ('ba', 'башҡорт теле');
|
||||
insert into language(code, name) values ('be', 'беларуская мова');
|
||||
insert into language(code, name) values ('bg', 'български език');
|
||||
insert into language(code, name) values ('bi', 'Bislama');
|
||||
insert into language(code, name) values ('bm', 'bamanankan');
|
||||
insert into language(code, name) values ('bn', 'বাংলা');
|
||||
insert into language(code, name) values ('bo', 'བོད་ཡིག');
|
||||
insert into language(code, name) values ('br', 'brezhoneg');
|
||||
insert into language(code, name) values ('bs', 'bosanski jezik');
|
||||
insert into language(code, name) values ('ca', 'Català');
|
||||
insert into language(code, name) values ('ce', 'нохчийн мотт');
|
||||
insert into language(code, name) values ('ch', 'Chamoru');
|
||||
insert into language(code, name) values ('co', 'corsu');
|
||||
insert into language(code, name) values ('cr', 'ᓀᐦᐃᔭᐍᐏᐣ');
|
||||
insert into language(code, name) values ('cs', 'čeština');
|
||||
insert into language(code, name) values ('cu', 'ѩзыкъ словѣньскъ');
|
||||
insert into language(code, name) values ('cv', 'чӑваш чӗлхи');
|
||||
insert into language(code, name) values ('cy', 'Cymraeg');
|
||||
insert into language(code, name) values ('da', 'dansk');
|
||||
insert into language(code, name) values ('de', 'Deutsch');
|
||||
insert into language(code, name) values ('dv', 'ދިވެހި');
|
||||
insert into language(code, name) values ('dz', 'རྫོང་ཁ');
|
||||
insert into language(code, name) values ('ee', 'Eʋegbe');
|
||||
insert into language(code, name) values ('el', 'Ελληνικά');
|
||||
insert into language(code, name) values ('en', 'English');
|
||||
insert into language(code, name) values ('eo', 'Esperanto');
|
||||
insert into language(code, name) values ('es', 'Español');
|
||||
insert into language(code, name) values ('et', 'eesti');
|
||||
insert into language(code, name) values ('eu', 'euskara');
|
||||
insert into language(code, name) values ('fa', 'فارسی');
|
||||
insert into language(code, name) values ('ff', 'Fulfulde');
|
||||
insert into language(code, name) values ('fi', 'suomi');
|
||||
insert into language(code, name) values ('fj', 'vosa Vakaviti');
|
||||
insert into language(code, name) values ('fo', 'føroyskt');
|
||||
insert into language(code, name) values ('fr', 'Français');
|
||||
insert into language(code, name) values ('fy', 'Frysk');
|
||||
insert into language(code, name) values ('ga', 'Gaeilge');
|
||||
insert into language(code, name) values ('gd', 'Gàidhlig');
|
||||
insert into language(code, name) values ('gl', 'galego');
|
||||
insert into language(code, name) values ('gn', E'Avañe\'ẽ');
|
||||
insert into language(code, name) values ('gu', 'ગુજરાતી');
|
||||
insert into language(code, name) values ('gv', 'Gaelg');
|
||||
insert into language(code, name) values ('ha', 'هَوُسَ');
|
||||
insert into language(code, name) values ('he', 'עברית');
|
||||
insert into language(code, name) values ('hi', 'हिन्दी');
|
||||
insert into language(code, name) values ('ho', 'Hiri Motu');
|
||||
insert into language(code, name) values ('hr', 'Hrvatski');
|
||||
insert into language(code, name) values ('ht', 'Kreyòl ayisyen');
|
||||
insert into language(code, name) values ('hu', 'magyar');
|
||||
insert into language(code, name) values ('hy', 'Հայերեն');
|
||||
insert into language(code, name) values ('hz', 'Otjiherero');
|
||||
insert into language(code, name) values ('ia', 'Interlingua');
|
||||
insert into language(code, name) values ('id', 'Bahasa Indonesia');
|
||||
insert into language(code, name) values ('ie', 'Interlingue');
|
||||
insert into language(code, name) values ('ig', 'Asụsụ Igbo');
|
||||
insert into language(code, name) values ('ii', 'ꆈꌠ꒿ Nuosuhxop');
|
||||
insert into language(code, name) values ('ik', 'Iñupiaq');
|
||||
insert into language(code, name) values ('io', 'Ido');
|
||||
insert into language(code, name) values ('is', 'Íslenska');
|
||||
insert into language(code, name) values ('it', 'Italiano');
|
||||
insert into language(code, name) values ('iu', 'ᐃᓄᒃᑎᑐᑦ');
|
||||
insert into language(code, name) values ('ja', '日本語');
|
||||
insert into language(code, name) values ('jv', 'basa Jawa');
|
||||
insert into language(code, name) values ('ka', 'ქართული');
|
||||
insert into language(code, name) values ('kg', 'Kikongo');
|
||||
insert into language(code, name) values ('ki', 'Gĩkũyũ');
|
||||
insert into language(code, name) values ('kj', 'Kuanyama');
|
||||
insert into language(code, name) values ('kk', 'қазақ тілі');
|
||||
insert into language(code, name) values ('kl', 'kalaallisut');
|
||||
insert into language(code, name) values ('km', 'ខេមរភាសា');
|
||||
insert into language(code, name) values ('kn', 'ಕನ್ನಡ');
|
||||
insert into language(code, name) values ('ko', '한국어');
|
||||
insert into language(code, name) values ('kr', 'Kanuri');
|
||||
insert into language(code, name) values ('ks', 'कश्मीरी');
|
||||
insert into language(code, name) values ('ku', 'Kurdî');
|
||||
insert into language(code, name) values ('kv', 'коми кыв');
|
||||
insert into language(code, name) values ('kw', 'Kernewek');
|
||||
insert into language(code, name) values ('ky', 'Кыргызча');
|
||||
insert into language(code, name) values ('la', 'latine');
|
||||
insert into language(code, name) values ('lb', 'Lëtzebuergesch');
|
||||
insert into language(code, name) values ('lg', 'Luganda');
|
||||
insert into language(code, name) values ('li', 'Limburgs');
|
||||
insert into language(code, name) values ('ln', 'Lingála');
|
||||
insert into language(code, name) values ('lo', 'ພາສາລາວ');
|
||||
insert into language(code, name) values ('lt', 'lietuvių kalba');
|
||||
insert into language(code, name) values ('lu', 'Kiluba');
|
||||
insert into language(code, name) values ('lv', 'latviešu valoda');
|
||||
insert into language(code, name) values ('mg', 'fiteny malagasy');
|
||||
insert into language(code, name) values ('mh', 'Kajin M̧ajeļ');
|
||||
insert into language(code, name) values ('mi', 'te reo Māori');
|
||||
insert into language(code, name) values ('mk', 'македонски јазик');
|
||||
insert into language(code, name) values ('ml', 'മലയാളം');
|
||||
insert into language(code, name) values ('mn', 'Монгол хэл');
|
||||
insert into language(code, name) values ('mr', 'मराठी');
|
||||
insert into language(code, name) values ('ms', 'Bahasa Melayu');
|
||||
insert into language(code, name) values ('mt', 'Malti');
|
||||
insert into language(code, name) values ('my', 'ဗမာစာ');
|
||||
insert into language(code, name) values ('na', 'Dorerin Naoero');
|
||||
insert into language(code, name) values ('nb', 'Norsk bokmål');
|
||||
insert into language(code, name) values ('nd', 'isiNdebele');
|
||||
insert into language(code, name) values ('ne', 'नेपाली');
|
||||
insert into language(code, name) values ('ng', 'Owambo');
|
||||
insert into language(code, name) values ('nl', 'Nederlands');
|
||||
insert into language(code, name) values ('nn', 'Norsk nynorsk');
|
||||
insert into language(code, name) values ('no', 'Norsk');
|
||||
insert into language(code, name) values ('nr', 'isiNdebele');
|
||||
insert into language(code, name) values ('nv', 'Diné bizaad');
|
||||
insert into language(code, name) values ('ny', 'chiCheŵa');
|
||||
insert into language(code, name) values ('oc', 'occitan');
|
||||
insert into language(code, name) values ('oj', 'ᐊᓂᔑᓈᐯᒧᐎᓐ');
|
||||
insert into language(code, name) values ('om', 'Afaan Oromoo');
|
||||
insert into language(code, name) values ('or', 'ଓଡ଼ିଆ');
|
||||
insert into language(code, name) values ('os', 'ирон æвзаг');
|
||||
insert into language(code, name) values ('pa', 'ਪੰਜਾਬੀ');
|
||||
insert into language(code, name) values ('pi', 'पाऴि');
|
||||
insert into language(code, name) values ('pl', 'Polski');
|
||||
insert into language(code, name) values ('ps', 'پښتو');
|
||||
insert into language(code, name) values ('pt', 'Português');
|
||||
insert into language(code, name) values ('qu', 'Runa Simi');
|
||||
insert into language(code, name) values ('rm', 'rumantsch grischun');
|
||||
insert into language(code, name) values ('rn', 'Ikirundi');
|
||||
insert into language(code, name) values ('ro', 'Română');
|
||||
insert into language(code, name) values ('ru', 'Русский');
|
||||
insert into language(code, name) values ('rw', 'Ikinyarwanda');
|
||||
insert into language(code, name) values ('sa', 'संस्कृतम्');
|
||||
insert into language(code, name) values ('sc', 'sardu');
|
||||
insert into language(code, name) values ('sd', 'सिन्धी');
|
||||
insert into language(code, name) values ('se', 'Davvisámegiella');
|
||||
insert into language(code, name) values ('sg', 'yângâ tî sängö');
|
||||
insert into language(code, name) values ('si', 'සිංහල');
|
||||
insert into language(code, name) values ('sk', 'slovenčina');
|
||||
insert into language(code, name) values ('sl', 'slovenščina');
|
||||
insert into language(code, name) values ('sm', E'gagana fa\'a Samoa');
|
||||
insert into language(code, name) values ('sn', 'chiShona');
|
||||
insert into language(code, name) values ('so', 'Soomaaliga');
|
||||
insert into language(code, name) values ('sq', 'Shqip');
|
||||
insert into language(code, name) values ('sr', 'српски језик');
|
||||
insert into language(code, name) values ('ss', 'SiSwati');
|
||||
insert into language(code, name) values ('st', 'Sesotho');
|
||||
insert into language(code, name) values ('su', 'Basa Sunda');
|
||||
insert into language(code, name) values ('sv', 'Svenska');
|
||||
insert into language(code, name) values ('sw', 'Kiswahili');
|
||||
insert into language(code, name) values ('ta', 'தமிழ்');
|
||||
insert into language(code, name) values ('te', 'తెలుగు');
|
||||
insert into language(code, name) values ('tg', 'тоҷикӣ');
|
||||
insert into language(code, name) values ('th', 'ไทย');
|
||||
insert into language(code, name) values ('ti', 'ትግርኛ');
|
||||
insert into language(code, name) values ('tk', 'Türkmençe');
|
||||
insert into language(code, name) values ('tl', 'Wikang Tagalog');
|
||||
insert into language(code, name) values ('tn', 'Setswana');
|
||||
insert into language(code, name) values ('to', 'faka Tonga');
|
||||
insert into language(code, name) values ('tr', 'Türkçe');
|
||||
insert into language(code, name) values ('ts', 'Xitsonga');
|
||||
insert into language(code, name) values ('tt', 'татар теле');
|
||||
insert into language(code, name) values ('tw', 'Twi');
|
||||
insert into language(code, name) values ('ty', 'Reo Tahiti');
|
||||
insert into language(code, name) values ('ug', 'ئۇيغۇرچە');
|
||||
insert into language(code, name) values ('uk', 'Українська');
|
||||
insert into language(code, name) values ('ur', 'اردو');
|
||||
insert into language(code, name) values ('uz', 'Ўзбек');
|
||||
insert into language(code, name) values ('ve', 'Tshivenḓa');
|
||||
insert into language(code, name) values ('vi', 'Tiếng Việt');
|
||||
insert into language(code, name) values ('vo', 'Volapük');
|
||||
insert into language(code, name) values ('wa', 'walon');
|
||||
insert into language(code, name) values ('wo', 'Wollof');
|
||||
insert into language(code, name) values ('xh', 'isiXhosa');
|
||||
insert into language(code, name) values ('yi', 'ייִדיש');
|
||||
insert into language(code, name) values ('yo', 'Yorùbá');
|
||||
insert into language(code, name) values ('za', 'Saɯ cueŋƅ');
|
||||
insert into language(code, name) values ('zh', '中文');
|
||||
insert into language(code, name) values ('zu', 'isiZulu');
|
Loading…
Reference in a new issue