diff --git a/Cargo.lock b/Cargo.lock
index 5ef691e26d..0ce7859e49 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -157,7 +157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb"
 dependencies = [
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -315,7 +315,7 @@ dependencies = [
  "actix-router",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -533,18 +533,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
 name = "async-trait"
-version = "0.1.77"
+version = "0.1.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9"
+checksum = "461abc97219de0eaaf81fe3ef974a540158f3d079c2ab200f891f1a2ef201e85"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -656,6 +656,12 @@ version = "0.21.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
 
+[[package]]
+name = "base64"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51"
+
 [[package]]
 name = "base64ct"
 version = "1.6.0"
@@ -687,11 +693,11 @@ dependencies = [
 
 [[package]]
 name = "bcrypt"
-version = "0.15.0"
+version = "0.15.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d1c9c15093eb224f0baa400f38fcd713fc1391a6f1c389d886beef146d60a3"
+checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7"
 dependencies = [
- "base64 0.21.7",
+ "base64 0.22.0",
  "blowfish",
  "getrandom",
  "subtle",
@@ -764,9 +770,9 @@ checksum = "bfb5ea45aeb912f2dd334834e64ecf674a6673d57c73e9d12de0298b9bf98ee8"
 
 [[package]]
 name = "brotli"
-version = "3.4.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "516074a47ef4bce09577a3b379392300159ce5b1ba2e501ff1c819950066100f"
+checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
 dependencies = [
  "alloc-no-stdlib",
  "alloc-stdlib",
@@ -926,9 +932,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.2"
+version = "4.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b230ab84b0ffdf890d5a10abdbc8b83ae1c4918275daea1ab8801f71536b2651"
+checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -948,14 +954,14 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.0"
+version = "4.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
+checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f"
 dependencies = [
- "heck",
+ "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -975,9 +981,9 @@ dependencies = [
 
 [[package]]
 name = "color-eyre"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204"
+checksum = "55146f5e46f237f7423d74111267d4597b59b0dad0ffaf7303bce9945d843ad5"
 dependencies = [
  "backtrace",
  "color-spantrace",
@@ -1034,7 +1040,7 @@ dependencies = [
  "ron",
  "serde",
  "serde_json",
- "toml 0.8.11",
+ "toml 0.8.12",
  "yaml-rust",
 ]
 
@@ -1297,7 +1303,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim 0.10.0",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -1330,7 +1336,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
 dependencies = [
  "darling_core 0.20.8",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -1466,9 +1472,9 @@ dependencies = [
 
 [[package]]
 name = "diesel"
-version = "2.1.4"
+version = "2.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62c6fcf842f17f8c78ecf7c81d75c5ce84436b41ee07e03f490fbb5f5a8731d8"
+checksum = "03fc05c17098f21b89bc7d98fe1dd3cce2c11c2ad8e145f2a44fe08ed28eb559"
 dependencies = [
  "bitflags 2.4.2",
  "byteorder",
@@ -1503,33 +1509,33 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "81c5131a2895ef64741dad1d483f358c2a229a3a2d1b256778cdc5e146db64d4"
 dependencies = [
- "heck",
+ "heck 0.4.1",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
 name = "diesel-derive-newtype"
-version = "2.1.0"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7267437d5b12df60ae29bd97f8d120f1c3a6272d6f213551afa56bbb2ecfbb7"
+checksum = "f4ed4d69628c8de8eb4c3f50cddb0678cba3c5b4cbe3cb1067d4d6c62ca47e4e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
 name = "diesel_derives"
-version = "2.1.2"
+version = "2.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ef8337737574f55a468005a83499da720f20c65586241ffea339db9ecdfd2b44"
+checksum = "5d02eecb814ae714ffe61ddc2db2dd03e6c49a42e269b5001355500d431cce0c"
 dependencies = [
  "diesel_table_macro_syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -1559,7 +1565,7 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
 dependencies = [
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -1751,7 +1757,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -1993,7 +1999,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -2072,9 +2078,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "h2"
-version = "0.3.24"
+version = "0.3.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9"
+checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb"
 dependencies = [
  "bytes",
  "fnv",
@@ -2133,6 +2139,12 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
+[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
 [[package]]
 name = "hermit-abi"
 version = "0.3.9"
@@ -2367,7 +2379,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8215279f83f9b829403812f845aa2d0dd5966332aa2fd0334a375256f3dd0322"
 dependencies = [
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -2633,6 +2645,7 @@ version = "0.19.3"
 dependencies = [
  "activitypub_federation",
  "actix-web",
+ "anyhow",
  "chrono",
  "encoding",
  "enum-map",
@@ -2645,6 +2658,7 @@ dependencies = [
  "lemmy_db_views_moderator",
  "lemmy_utils",
  "mime",
+ "moka",
  "once_cell",
  "pretty_assertions",
  "regex",
@@ -3183,9 +3197,9 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 
 [[package]]
 name = "metrics"
-version = "0.22.0"
+version = "0.22.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77b9e10a211c839210fd7f99954bda26e5f8e26ec686ad68da6a32df7c80e782"
+checksum = "2be3cbd384d4e955b231c895ce10685e3d8260c5ccffae898c96c723b0772835"
 dependencies = [
  "ahash",
  "portable-atomic",
@@ -3210,9 +3224,9 @@ dependencies = [
 
 [[package]]
 name = "metrics-util"
-version = "0.16.2"
+version = "0.16.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ece71ab046dcf45604e573329966ec1db5ff4b81cfa170a924ff4c959ab5451a"
+checksum = "8b07a5eb561b8cbc16be2d216faf7757f9baf3bfb94dbb0fae3df8387a5bb47f"
 dependencies = [
  "crossbeam-epoch",
  "crossbeam-utils",
@@ -3353,9 +3367,9 @@ checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
 
 [[package]]
 name = "new_debug_unreachable"
-version = "1.0.4"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
 
 [[package]]
 name = "nom"
@@ -3460,7 +3474,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -3867,7 +3881,7 @@ dependencies = [
  "tokio-postgres",
  "tokio-postgres-rustls 0.11.1",
  "tokio-util",
- "toml 0.8.11",
+ "toml 0.8.12",
  "tracing",
  "tracing-actix-web",
  "tracing-error",
@@ -3896,7 +3910,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4116,7 +4130,7 @@ dependencies = [
  "itertools 0.11.0",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4260,7 +4274,7 @@ checksum = "a25d631e41bfb5fdcde1d4e2215f62f7f0afa3ff11e26563765bd6ea1d229aeb"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4303,12 +4317,12 @@ dependencies = [
  "postgres",
  "regex",
  "serde",
- "siphasher 1.0.0",
+ "siphasher 1.0.1",
  "thiserror",
  "time",
  "tokio",
  "tokio-postgres",
- "toml 0.8.11",
+ "toml 0.8.12",
  "url",
  "walkdir",
 ]
@@ -4323,7 +4337,7 @@ dependencies = [
  "quote",
  "refinery-core",
  "regex",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4420,9 +4434,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest-middleware"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88a3e86aa6053e59030e7ce2d2a3b258dd08fc2d337d52f73f6cb480f5858690"
+checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -4435,9 +4449,9 @@ dependencies = [
 
 [[package]]
 name = "reqwest-tracing"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a0152176687dd5cfe7f507ac1cb1a491c679cfe483afd133a7db7aaea818bb3"
+checksum = "190838e54153d7a7e2ea98851304b3ce92daeabf14c54d32b01b84a3e636f683"
 dependencies = [
  "anyhow",
  "async-trait",
@@ -4832,7 +4846,7 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4904,7 +4918,7 @@ dependencies = [
  "darling 0.20.8",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -4929,7 +4943,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -5007,9 +5021,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
 
 [[package]]
 name = "siphasher"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe"
+checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
 
 [[package]]
 name = "sitemap-rs"
@@ -5081,7 +5095,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -5209,11 +5223,11 @@ version = "0.25.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0"
 dependencies = [
- "heck",
+ "heck 0.4.1",
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -5235,9 +5249,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.52"
+version = "2.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
+checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5357,7 +5371,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -5460,7 +5474,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -5562,9 +5576,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.14"
+version = "0.1.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
+checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -5599,14 +5613,14 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.8.11"
+version = "0.8.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e"
+checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3"
 dependencies = [
  "serde",
  "serde_spanned",
  "toml_datetime",
- "toml_edit 0.22.7",
+ "toml_edit 0.22.8",
 ]
 
 [[package]]
@@ -5633,9 +5647,9 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.22.7"
+version = "0.22.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992"
+checksum = "c12219811e0c1ba077867254e5ad62ee2c9c190b0d957110750ac0cda1ae96cd"
 dependencies = [
  "indexmap 2.2.5",
  "serde",
@@ -5841,7 +5855,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -6004,7 +6018,7 @@ dependencies = [
  "Inflector",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
  "termcolor",
 ]
 
@@ -6025,7 +6039,7 @@ checksum = "563b3b88238ec95680aef36bdece66896eaa7ce3c0f1b4f39d38fb2435261352"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -6132,9 +6146,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
 name = "uuid"
-version = "1.7.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
+checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
 dependencies = [
  "atomic",
  "getrandom",
@@ -6211,7 +6225,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
  "wasm-bindgen-shared",
 ]
 
@@ -6245,7 +6259,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6704,7 +6718,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
@@ -6724,7 +6738,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.52",
+ "syn 2.0.53",
 ]
 
 [[package]]
diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs
index 40065672c5..5f811cb0d9 100644
--- a/crates/db_views/src/comment_view.rs
+++ b/crates/db_views/src/comment_view.rs
@@ -53,6 +53,16 @@ fn queries<'a>() -> Queries<
     ),
   );
 
+  let is_local_user_banned_from_community = |person_id| {
+    exists(
+      community_person_ban::table.filter(
+        community::id
+          .eq(community_person_ban::community_id)
+          .and(community_person_ban::person_id.eq(person_id)),
+      ),
+    )
+  };
+
   let is_saved = |person_id| {
     comment_saved::table
       .filter(
@@ -113,6 +123,14 @@ fn queries<'a>() -> Queries<
   );
 
   let all_joins = move |query: comment::BoxedQuery<'a, Pg>, my_person_id: Option<PersonId>| {
+    let is_local_user_banned_from_community_selection: Box<
+      dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>,
+    > = if let Some(person_id) = my_person_id {
+      Box::new(is_local_user_banned_from_community(person_id))
+    } else {
+      Box::new(false.into_sql::<sql_types::Bool>())
+    };
+
     let score_selection: Box<
       dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
     > = if let Some(person_id) = my_person_id {
@@ -156,6 +174,7 @@ fn queries<'a>() -> Queries<
         community::all_columns,
         comment_aggregates::all_columns,
         is_creator_banned_from_community,
+        is_local_user_banned_from_community_selection,
         creator_is_moderator,
         creator_is_admin,
         subscribed_type_selection,
@@ -436,6 +455,8 @@ mod tests {
         CommunityInsertForm,
         CommunityModerator,
         CommunityModeratorForm,
+        CommunityPersonBan,
+        CommunityPersonBanForm,
         CommunityUpdateForm,
       },
       instance::Instance,
@@ -446,11 +467,12 @@ mod tests {
       person_block::{PersonBlock, PersonBlockForm},
       post::{Post, PostInsertForm},
     },
-    traits::{Blockable, Crud, Joinable, Likeable, Saveable},
+    traits::{Bannable, Blockable, Crud, Joinable, Likeable, Saveable},
     utils::{build_db_pool_for_tests, RANK_DEFAULT},
     CommunityVisibility,
     SubscribedType,
   };
+  use lemmy_utils::error::LemmyResult;
   use pretty_assertions::assert_eq;
   use serial_test::serial;
 
@@ -633,12 +655,12 @@ mod tests {
 
   #[tokio::test]
   #[serial]
-  async fn test_crud() {
+  async fn test_crud() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
 
-    let expected_comment_view_no_person = expected_comment_view(&data, pool).await;
+    let expected_comment_view_no_person = expected_comment_view(&data, pool).await?;
 
     let mut expected_comment_view_with_person = expected_comment_view_no_person.clone();
     expected_comment_view_with_person.my_vote = Some(1);
@@ -649,8 +671,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     assert_eq!(
       expected_comment_view_no_person,
@@ -664,8 +685,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     assert_eq!(
       expected_comment_view_with_person,
@@ -680,8 +700,7 @@ mod tests {
       data.inserted_comment_1.id,
       Some(data.timmy_local_user_view.person.id),
     )
-    .await
-    .unwrap();
+    .await?;
 
     // Make sure block set the creator blocked
     assert!(read_comment_from_blocked_person.creator_blocked);
@@ -692,8 +711,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     assert_eq!(
       expected_comment_view_with_person,
@@ -708,17 +726,16 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     assert!(read_disliked_comment_views.is_empty());
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_comment_tree() {
+  async fn test_comment_tree() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -730,8 +747,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     let child_path = data.inserted_comment_1.path.clone();
     let read_comment_views_child_path = CommentQuery {
@@ -740,8 +756,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     // Make sure the comment parent-limited fetch is correct
     assert_length!(6, read_comment_views_top_path);
@@ -761,12 +776,11 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     // Make sure a depth limited one only has the top comment
     assert_eq!(
-      expected_comment_view(&data, pool).await,
+      expected_comment_view(&data, pool).await?,
       read_comment_views_top_max_depth[0]
     );
     assert_length!(1, read_comment_views_top_max_depth);
@@ -780,8 +794,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     // Make sure a depth limited one, and given child comment 1, has 3
     assert!(read_comment_views_parent_max_depth[2]
@@ -790,12 +803,12 @@ mod tests {
       .eq("Comment 3"));
     assert_length!(3, read_comment_views_parent_max_depth);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_languages() {
+  async fn test_languages() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -807,29 +820,25 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_length!(5, all_languages);
 
     // change user lang to finnish, should only show one post in finnish and one undetermined
     let finnish_id = Language::read_id_from_code(pool, Some("fi"))
-      .await
-      .unwrap()
+      .await?
       .unwrap();
     LocalUserLanguage::update(
       pool,
       vec![finnish_id],
       data.timmy_local_user_view.local_user.id,
     )
-    .await
-    .unwrap();
+    .await?;
     let finnish_comments = CommentQuery {
       local_user: (Some(&data.timmy_local_user_view)),
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_length!(2, finnish_comments);
     let finnish_comment = finnish_comments
       .iter()
@@ -846,23 +855,21 @@ mod tests {
       vec![UNDETERMINED_ID],
       data.timmy_local_user_view.local_user.id,
     )
-    .await
-    .unwrap();
+    .await?;
     let undetermined_comment = CommentQuery {
       local_user: (Some(&data.timmy_local_user_view)),
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_length!(1, undetermined_comment);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_distinguished_first() {
+  async fn test_distinguished_first() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -871,26 +878,23 @@ mod tests {
       distinguished: Some(true),
       ..Default::default()
     };
-    Comment::update(pool, data.inserted_comment_2.id, &form)
-      .await
-      .unwrap();
+    Comment::update(pool, data.inserted_comment_2.id, &form).await?;
 
     let comments = CommentQuery {
       post_id: Some(data.inserted_comment_2.post_id),
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_eq!(comments[0].comment.id, data.inserted_comment_2.id);
     assert!(comments[0].comment.distinguished);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_creator_is_moderator() {
+  async fn test_creator_is_moderator() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -902,7 +906,7 @@ mod tests {
       community_id,
       person_id,
     };
-    CommunityModerator::join(pool, &form).await.unwrap();
+    CommunityModerator::join(pool, &form).await?;
 
     // Make sure that they come back as a mod in the list
     let comments = CommentQuery {
@@ -910,19 +914,18 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     assert_eq!(comments[1].creator.name, "sara");
     assert!(comments[1].creator_is_moderator);
     assert!(!comments[0].creator_is_moderator);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_creator_is_admin() {
+  async fn test_creator_is_admin() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -932,8 +935,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     // Timmy is an admin, and make sure that field is true
     assert_eq!(comments[0].creator.name, "timmy");
@@ -943,12 +945,12 @@ mod tests {
     assert_eq!(comments[1].creator.name, "sara");
     assert!(!comments[1].creator_is_admin);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
   #[tokio::test]
   #[serial]
-  async fn test_saved_order() {
+  async fn test_saved_order() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -958,17 +960,13 @@ mod tests {
       person_id: data.timmy_local_user_view.person.id,
       comment_id: data.inserted_comment_0.id,
     };
-    CommentSaved::save(pool, &save_comment_0_form)
-      .await
-      .unwrap();
+    CommentSaved::save(pool, &save_comment_0_form).await?;
 
     let save_comment_2_form = CommentSavedForm {
       person_id: data.timmy_local_user_view.person.id,
       comment_id: data.inserted_comment_2.id,
     };
-    CommentSaved::save(pool, &save_comment_2_form)
-      .await
-      .unwrap();
+    CommentSaved::save(pool, &save_comment_2_form).await?;
 
     // Fetch the saved comments
     let comments = CommentQuery {
@@ -977,8 +975,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
 
     // There should only be two comments
     assert_eq!(2, comments.len());
@@ -989,47 +986,33 @@ mod tests {
     // The second comment, should be the first one saved
     assert_eq!(comments[1].comment.id, data.inserted_comment_0.id);
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
   }
 
-  async fn cleanup(data: Data, pool: &mut DbPool<'_>) {
+  async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> {
     CommentLike::remove(
       pool,
       data.timmy_local_user_view.person.id,
       data.inserted_comment_0.id,
     )
-    .await
-    .unwrap();
-    Comment::delete(pool, data.inserted_comment_0.id)
-      .await
-      .unwrap();
-    Comment::delete(pool, data.inserted_comment_1.id)
-      .await
-      .unwrap();
-    Post::delete(pool, data.inserted_post.id).await.unwrap();
-    Community::delete(pool, data.inserted_community.id)
-      .await
-      .unwrap();
-    Person::delete(pool, data.timmy_local_user_view.person.id)
-      .await
-      .unwrap();
-    LocalUser::delete(pool, data.timmy_local_user_view.local_user.id)
-      .await
-      .unwrap();
-    Person::delete(pool, data.inserted_sara_person.id)
-      .await
-      .unwrap();
-    Instance::delete(pool, data.inserted_instance.id)
-      .await
-      .unwrap();
+    .await?;
+    Comment::delete(pool, data.inserted_comment_0.id).await?;
+    Comment::delete(pool, data.inserted_comment_1.id).await?;
+    Post::delete(pool, data.inserted_post.id).await?;
+    Community::delete(pool, data.inserted_community.id).await?;
+    Person::delete(pool, data.timmy_local_user_view.person.id).await?;
+    LocalUser::delete(pool, data.timmy_local_user_view.local_user.id).await?;
+    Person::delete(pool, data.inserted_sara_person.id).await?;
+    Instance::delete(pool, data.inserted_instance.id).await?;
+
+    Ok(())
   }
 
-  async fn expected_comment_view(data: &Data, pool: &mut DbPool<'_>) -> CommentView {
-    let agg = CommentAggregates::read(pool, data.inserted_comment_0.id)
-      .await
-      .unwrap();
-    CommentView {
+  async fn expected_comment_view(data: &Data, pool: &mut DbPool<'_>) -> LemmyResult<CommentView> {
+    let agg = CommentAggregates::read(pool, data.inserted_comment_0.id).await?;
+    Ok(CommentView {
       creator_banned_from_community: false,
+      banned_from_community: false,
       creator_is_moderator: false,
       creator_is_admin: true,
       my_vote: None,
@@ -1136,12 +1119,12 @@ mod tests {
         hot_rank: RANK_DEFAULT,
         controversy_rank: 0.0,
       },
-    }
+    })
   }
 
   #[tokio::test]
   #[serial]
-  async fn local_only_instance() {
+  async fn local_only_instance() -> LemmyResult<()> {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
     let data = init_data(pool).await;
@@ -1154,15 +1137,13 @@ mod tests {
         ..Default::default()
       },
     )
-    .await
-    .unwrap();
+    .await?;
 
     let unauthenticated_query = CommentQuery {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_eq!(0, unauthenticated_query.len());
 
     let authenticated_query = CommentQuery {
@@ -1170,8 +1151,7 @@ mod tests {
       ..Default::default()
     }
     .list(pool)
-    .await
-    .unwrap();
+    .await?;
     assert_eq!(5, authenticated_query.len());
 
     let unauthenticated_comment = CommentView::read(pool, data.inserted_comment_0.id, None).await;
@@ -1185,6 +1165,66 @@ mod tests {
     .await;
     assert!(authenticated_comment.is_ok());
 
-    cleanup(data, pool).await;
+    cleanup(data, pool).await
+  }
+
+  #[tokio::test]
+  #[serial]
+  async fn comment_listing_local_user_banned_from_community() -> LemmyResult<()> {
+    let pool = &build_db_pool_for_tests().await;
+    let pool = &mut pool.into();
+    let data = init_data(pool).await;
+
+    // Test that comment view shows if local user is blocked from community
+    let banned_from_comm_person = PersonInsertForm::test_form(data.inserted_instance.id, "jill");
+
+    let inserted_banned_from_comm_person = Person::create(pool, &banned_from_comm_person).await?;
+
+    let inserted_banned_from_comm_local_user = LocalUser::create(
+      pool,
+      &LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
+    )
+    .await?;
+
+    CommunityPersonBan::ban(
+      pool,
+      &CommunityPersonBanForm {
+        community_id: data.inserted_community.id,
+        person_id: inserted_banned_from_comm_person.id,
+        expires: None,
+      },
+    )
+    .await?;
+
+    let comment_view = CommentView::read(
+      pool,
+      data.inserted_comment_0.id,
+      Some(inserted_banned_from_comm_local_user.person_id),
+    )
+    .await?;
+
+    assert!(comment_view.banned_from_community);
+
+    Person::delete(pool, inserted_banned_from_comm_person.id).await?;
+    cleanup(data, pool).await
+  }
+
+  #[tokio::test]
+  #[serial]
+  async fn comment_listing_local_user_not_banned_from_community() -> LemmyResult<()> {
+    let pool = &build_db_pool_for_tests().await;
+    let pool = &mut pool.into();
+    let data = init_data(pool).await;
+
+    let comment_view = CommentView::read(
+      pool,
+      data.inserted_comment_0.id,
+      Some(data.timmy_local_user_view.person.id),
+    )
+    .await?;
+
+    assert!(!comment_view.banned_from_community);
+
+    cleanup(data, pool).await
   }
 }
diff --git a/crates/db_views/src/custom_emoji_view.rs b/crates/db_views/src/custom_emoji_view.rs
index d83fa9912a..4d2f1fd859 100644
--- a/crates/db_views/src/custom_emoji_view.rs
+++ b/crates/db_views/src/custom_emoji_view.rs
@@ -77,7 +77,7 @@ impl CustomEmojiView {
     }
     for emoji in &mut result {
       if let Some(keywords) = hash.get_mut(&emoji.custom_emoji.id) {
-        emoji.keywords = keywords.clone();
+        emoji.keywords.clone_from(keywords);
       }
     }
     result
diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs
index b9522d47b4..ae5ec383a1 100644
--- a/crates/db_views/src/post_view.rs
+++ b/crates/db_views/src/post_view.rs
@@ -73,6 +73,17 @@ fn queries<'a>() -> Queries<
         .and(community_person_ban::person_id.eq(post_aggregates::creator_id)),
     ),
   );
+
+  let is_local_user_banned_from_community = |person_id| {
+    exists(
+      community_person_ban::table.filter(
+        post_aggregates::community_id
+          .eq(community_person_ban::community_id)
+          .and(community_person_ban::person_id.eq(person_id)),
+      ),
+    )
+  };
+
   let creator_is_moderator = exists(
     community_moderator::table.filter(
       post_aggregates::community_id
@@ -143,6 +154,14 @@ fn queries<'a>() -> Queries<
 
   let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>,
                         my_person_id: Option<PersonId>| {
+    let is_local_user_banned_from_community_selection: Box<
+      dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>,
+    > = if let Some(person_id) = my_person_id {
+      Box::new(is_local_user_banned_from_community(person_id))
+    } else {
+      Box::new(false.into_sql::<sql_types::Bool>())
+    };
+
     let is_saved_selection: Box<
       dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::Timestamptz>>,
     > = if let Some(person_id) = my_person_id {
@@ -223,6 +242,7 @@ fn queries<'a>() -> Queries<
         person::all_columns,
         community::all_columns,
         is_creator_banned_from_community,
+        is_local_user_banned_from_community_selection,
         creator_is_moderator,
         creator_is_admin,
         post_aggregates::all_columns,
@@ -742,6 +762,8 @@ mod tests {
         CommunityInsertForm,
         CommunityModerator,
         CommunityModeratorForm,
+        CommunityPersonBan,
+        CommunityPersonBanForm,
         CommunityUpdateForm,
       },
       community_block::{CommunityBlock, CommunityBlockForm},
@@ -755,7 +777,7 @@ mod tests {
       post::{Post, PostHide, PostInsertForm, PostLike, PostLikeForm, PostRead, PostUpdateForm},
       site::Site,
     },
-    traits::{Blockable, Crud, Joinable, Likeable},
+    traits::{Bannable, Blockable, Crud, Joinable, Likeable},
     utils::{build_db_pool, build_db_pool_for_tests, DbPool, RANK_DEFAULT},
     CommunityVisibility,
     SortType,
@@ -1604,6 +1626,7 @@ mod tests {
         last_refreshed_at: inserted_person.last_refreshed_at,
       },
       creator_banned_from_community: false,
+      banned_from_community: false,
       creator_is_moderator: false,
       creator_is_admin: true,
       community: Community {
@@ -1707,4 +1730,66 @@ mod tests {
     cleanup(data, pool).await?;
     Ok(())
   }
+
+  #[tokio::test]
+  #[serial]
+  async fn post_listing_local_user_banned_from_community() -> LemmyResult<()> {
+    let pool = &build_db_pool().await?;
+    let pool = &mut pool.into();
+    let data = init_data(pool).await?;
+
+    // Test that post view shows if local user is blocked from community
+    let banned_from_comm_person = PersonInsertForm::test_form(data.inserted_instance.id, "jill");
+
+    let inserted_banned_from_comm_person = Person::create(pool, &banned_from_comm_person).await?;
+
+    let inserted_banned_from_comm_local_user = LocalUser::create(
+      pool,
+      &LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
+    )
+    .await?;
+
+    CommunityPersonBan::ban(
+      pool,
+      &CommunityPersonBanForm {
+        community_id: data.inserted_community.id,
+        person_id: inserted_banned_from_comm_person.id,
+        expires: None,
+      },
+    )
+    .await?;
+
+    let post_view = PostView::read(
+      pool,
+      data.inserted_post.id,
+      Some(inserted_banned_from_comm_local_user.person_id),
+      false,
+    )
+    .await?;
+
+    assert!(post_view.banned_from_community);
+
+    Person::delete(pool, inserted_banned_from_comm_person.id).await?;
+    cleanup(data, pool).await
+  }
+
+  #[tokio::test]
+  #[serial]
+  async fn post_listing_local_user_not_banned_from_community() -> LemmyResult<()> {
+    let pool = &build_db_pool().await?;
+    let pool = &mut pool.into();
+    let data = init_data(pool).await?;
+
+    let post_view = PostView::read(
+      pool,
+      data.inserted_post.id,
+      Some(data.local_user_view.person.id),
+      false,
+    )
+    .await?;
+
+    assert!(!post_view.banned_from_community);
+
+    cleanup(data, pool).await
+  }
 }
diff --git a/crates/db_views/src/structs.rs b/crates/db_views/src/structs.rs
index 18fa7efa9a..cfaee591dc 100644
--- a/crates/db_views/src/structs.rs
+++ b/crates/db_views/src/structs.rs
@@ -64,6 +64,7 @@ pub struct CommentView {
   pub community: Community,
   pub counts: CommentAggregates,
   pub creator_banned_from_community: bool,
+  pub banned_from_community: bool,
   pub creator_is_moderator: bool,
   pub creator_is_admin: bool,
   pub subscribed: SubscribedType,
@@ -129,6 +130,7 @@ pub struct PostView {
   pub creator: Person,
   pub community: Community,
   pub creator_banned_from_community: bool,
+  pub banned_from_community: bool,
   pub creator_is_moderator: bool,
   pub creator_is_admin: bool,
   pub counts: PostAggregates,