]> Untitled Git - lemmy.git/commitdiff
Enforce site and community bans for federated users
authorFelix Ableitner <me@nutomic.com>
Mon, 9 Nov 2020 14:29:36 +0000 (15:29 +0100)
committerFelix Ableitner <me@nutomic.com>
Mon, 9 Nov 2020 14:29:36 +0000 (15:29 +0100)
lemmy_api/src/user.rs
lemmy_apub/src/inbox/community_inbox.rs
lemmy_apub/src/inbox/receive_for_community.rs
lemmy_apub/src/objects/user.rs
lemmy_db/src/user.rs
src/code_migrations.rs

index 6dffc1a792b0c09c0a31b2928c0b86419858524a..41f77271ac4d5e17ae93e74391044e69dfa2047b 100644 (file)
@@ -175,7 +175,7 @@ impl Perform for Register {
       published: None,
       updated: None,
       admin: data.admin,
-      banned: false,
+      banned: Some(false),
       show_nsfw: data.show_nsfw,
       theme: "browser".into(),
       default_sort_type: SortType::Active as i16,
@@ -407,7 +407,7 @@ impl Perform for SaveUserSettings {
       published: Some(read_user.published),
       updated: Some(naive_now()),
       admin: read_user.admin,
-      banned: read_user.banned,
+      banned: Some(read_user.banned),
       show_nsfw: data.show_nsfw,
       theme: data.theme.to_owned(),
       default_sort_type: data.default_sort_type,
index 630a2db924091b0d9630b71075f934e57d5044c6..6cd4a017ff530526993131ee2f144b40c1926065 100644 (file)
@@ -27,7 +27,9 @@ use actix_web::{web, HttpRequest, HttpResponse};
 use anyhow::{anyhow, Context};
 use lemmy_db::{
   community::{Community, CommunityFollower, CommunityFollowerForm},
+  community_view::CommunityUserBanView,
   user::User_,
+  DbPool,
   Followable,
 };
 use lemmy_structs::blocking;
@@ -110,14 +112,21 @@ pub(crate) async fn community_receive_message(
   context: &LemmyContext,
   request_counter: &mut i32,
 ) -> Result<HttpResponse, LemmyError> {
-  // TODO: check if the sending user is banned by the community
+  // Only users can send activities to the community, so we can get the actor as user
+  // unconditionally.
+  let actor_id = actor.actor_id_str();
+  let user = blocking(&context.pool(), move |conn| {
+    User_::read_from_actor_id(&conn, &actor_id)
+  })
+  .await??;
+  check_community_or_site_ban(&user, &to_community, context.pool()).await?;
 
   let any_base = activity.clone().into_any_base()?;
   let actor_url = actor.actor_id()?;
   let activity_kind = activity.kind().context(location_info!())?;
   let do_announce = match activity_kind {
     CommunityValidTypes::Follow => {
-      handle_follow(any_base.clone(), actor_url, &to_community, &context).await?;
+      handle_follow(any_base.clone(), user, &to_community, &context).await?;
       false
     }
     CommunityValidTypes::Undo => {
@@ -172,17 +181,13 @@ pub(crate) async fn community_receive_message(
 /// Accept activity.
 async fn handle_follow(
   activity: AnyBase,
-  user_url: Url,
+  user: User_,
   community: &Community,
   context: &LemmyContext,
 ) -> Result<HttpResponse, LemmyError> {
   let follow = Follow::from_any_base(activity)?.context(location_info!())?;
-  verify_activity_domains_valid(&follow, &user_url, false)?;
+  verify_activity_domains_valid(&follow, &user.actor_id()?, false)?;
 
-  let user = blocking(&context.pool(), move |conn| {
-    User_::read_from_actor_id(&conn, user_url.as_str())
-  })
-  .await??;
   let community_follower_form = CommunityFollowerForm {
     community_id: community.id,
     user_id: user.id,
@@ -250,3 +255,21 @@ async fn handle_undo_follow(
 
   Ok(())
 }
+
+async fn check_community_or_site_ban(
+  user: &User_,
+  community: &Community,
+  pool: &DbPool,
+) -> Result<(), LemmyError> {
+  if user.banned {
+    return Err(anyhow!("User is banned from site").into());
+  }
+  let user_id = user.id;
+  let community_id = community.id;
+  let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
+  if blocking(pool, is_banned).await? {
+    return Err(anyhow!("User is banned from community").into());
+  }
+
+  Ok(())
+}
index d4cd43d774aca9436d9c44b655e28cfa120a8db8..b6dfa1e423683e942dc78290d512b272f6731b42 100644 (file)
@@ -135,7 +135,6 @@ pub(in crate::inbox) async fn receive_delete_for_community(
   activity: AnyBase,
   expected_domain: &Url,
 ) -> Result<(), LemmyError> {
-  dbg!("receive_delete_for_community");
   let delete = Delete::from_any_base(activity)?.context(location_info!())?;
   verify_activity_domains_valid(&delete, &expected_domain, true)?;
   is_addressed_to_public(&delete)?;
@@ -160,7 +159,6 @@ pub(in crate::inbox) async fn receive_remove_for_community(
   activity: AnyBase,
   expected_domain: &Url,
 ) -> Result<(), LemmyError> {
-  dbg!("receive_remove_for_community");
   let remove = Remove::from_any_base(activity)?.context(location_info!())?;
   verify_activity_domains_valid(&remove, &expected_domain, false)?;
   is_addressed_to_public(&remove)?;
index 5ef1ec8e9d7c20e9d3dee33578783967c91d6376..3c41b55848706e47f32719ec7725451114e09478 100644 (file)
@@ -132,7 +132,7 @@ impl FromApub for UserForm {
       preferred_username: Some(preferred_username),
       password_encrypted: "".to_string(),
       admin: false,
-      banned: false,
+      banned: None,
       email: None,
       avatar,
       banner,
index db8a999eb7d709bb2f2c06b86622e2da441e481c..8dc613bb3fbb6b66910fe8a57f0c8869bc45e71b 100644 (file)
@@ -46,7 +46,7 @@ pub struct UserForm {
   pub preferred_username: Option<Option<String>>,
   pub password_encrypted: String,
   pub admin: bool,
-  pub banned: bool,
+  pub banned: Option<bool>,
   pub email: Option<Option<String>>,
   pub avatar: Option<Option<String>>,
   pub published: Option<chrono::NaiveDateTime>,
index adc4ae49ae41b616d2c5b81444d2b278eb4d3852..c41f5bd966ae53c9a0bf90ecc7a6c3f0f4c43edf 100644 (file)
@@ -57,7 +57,7 @@ fn user_updates_2020_04_02(conn: &PgConnection) -> Result<(), LemmyError> {
       published: Some(cuser.published),
       updated: None,
       admin: cuser.admin,
-      banned: cuser.banned,
+      banned: Some(cuser.banned),
       show_nsfw: cuser.show_nsfw,
       theme: cuser.theme.to_owned(),
       default_sort_type: cuser.default_sort_type,