]> Untitled Git - lemmy.git/commitdiff
Added community delete and remove.
authorDessalines <tyhou13@gmx.com>
Mon, 20 Jul 2020 17:37:39 +0000 (13:37 -0400)
committerDessalines <tyhou13@gmx.com>
Mon, 20 Jul 2020 17:37:39 +0000 (13:37 -0400)
14 files changed:
docs/src/contributing_websocket_http_api.md
server/lemmy_db/src/community.rs
server/lemmy_db/src/community_view.rs
server/src/api/community.rs
server/src/routes/api.rs
server/src/websocket/mod.rs
server/src/websocket/server.rs
ui/src/api_tests/api.spec.ts
ui/src/components/community.tsx
ui/src/components/post.tsx
ui/src/components/sidebar.tsx
ui/src/interfaces.ts
ui/src/services/WebSocketService.ts
ui/translations/en.json

index 63d8f994bd5c34c2eea010b529d3d68504feaa55..4931ed583d3c281680c35bf87ca6e921df9bd29b 100644 (file)
@@ -1102,7 +1102,7 @@ Search types are `All, Comments, Posts, Communities, Users, Url`
 `POST /community/mod`
 
 #### Edit Community
-Mods and admins can remove and lock a community, creators can delete it.
+Only mods can edit a community.
 
 ##### Request
 ```rust
@@ -1113,10 +1113,6 @@ Mods and admins can remove and lock a community, creators can delete it.
     title: String,
     description: Option<String>,
     category_id: i32,
-    removed: Option<bool>,
-    deleted: Option<bool>,
-    reason: Option<String>,
-    expires: Option<i64>,
     auth: String
   }
 }
@@ -1134,6 +1130,62 @@ Mods and admins can remove and lock a community, creators can delete it.
 
 `PUT /community`
 
+#### Delete Community
+Only a creator can delete a community
+
+##### Request
+```rust
+{
+  op: "DeleteCommunity",
+  data: {
+    edit_id: i32,
+    deleted: bool,
+    auth: String,
+  }
+}
+```
+##### Response
+```rust
+{
+  op: "DeleteCommunity",
+  data: {
+    community: CommunityView
+  }
+}
+```
+##### HTTP
+
+`POST /community/delete`
+
+#### Remove Community
+Only admins can remove a community.
+
+##### Request
+```rust
+{
+  op: "RemoveCommunity",
+  data: {
+    edit_id: i32,
+    removed: bool,
+    reason: Option<String>,
+    expires: Option<i64>,
+    auth: String,
+  }
+}
+```
+##### Response
+```rust
+{
+  op: "RemoveCommunity",
+  data: {
+    community: CommunityView
+  }
+}
+```
+##### HTTP
+
+`POST /community/remove`
+
 #### Follow Community
 ##### Request
 ```rust
index e1f24391991f312771ab501ac7fddbf429149a5f..4fe507f72cc5c92bb19776d608b4a9ec04c99da0 100644 (file)
@@ -99,6 +99,39 @@ impl Community {
     use crate::schema::community::dsl::*;
     community.filter(local.eq(true)).load::<Community>(conn)
   }
+
+  pub fn update_deleted(
+    conn: &PgConnection,
+    community_id: i32,
+    new_deleted: bool,
+  ) -> Result<Self, Error> {
+    use crate::schema::community::dsl::*;
+    diesel::update(community.find(community_id))
+      .set(deleted.eq(new_deleted))
+      .get_result::<Self>(conn)
+  }
+
+  pub fn update_removed(
+    conn: &PgConnection,
+    community_id: i32,
+    new_removed: bool,
+  ) -> Result<Self, Error> {
+    use crate::schema::community::dsl::*;
+    diesel::update(community.find(community_id))
+      .set(removed.eq(new_removed))
+      .get_result::<Self>(conn)
+  }
+
+  pub fn update_creator(
+    conn: &PgConnection,
+    community_id: i32,
+    new_creator_id: i32,
+  ) -> Result<Self, Error> {
+    use crate::schema::community::dsl::*;
+    diesel::update(community.find(community_id))
+      .set(creator_id.eq(new_creator_id))
+      .get_result::<Self>(conn)
+  }
 }
 
 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
index 5c6bd81a19590dc2c0dd62ae221616cc7a2cd983..880c945591f5fa815b61c3a6ecea8489dd76acad 100644 (file)
@@ -295,18 +295,18 @@ pub struct CommunityModeratorView {
 }
 
 impl CommunityModeratorView {
-  pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result<Vec<Self>, Error> {
+  pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result<Vec<Self>, Error> {
     use super::community_view::community_moderator_view::dsl::*;
     community_moderator_view
-      .filter(community_id.eq(from_community_id))
+      .filter(community_id.eq(for_community_id))
       .order_by(published)
       .load::<Self>(conn)
   }
 
-  pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result<Vec<Self>, Error> {
+  pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result<Vec<Self>, Error> {
     use super::community_view::community_moderator_view::dsl::*;
     community_moderator_view
-      .filter(user_id.eq(from_user_id))
+      .filter(user_id.eq(for_user_id))
       .order_by(published)
       .load::<Self>(conn)
   }
index fc5cb0e61d6775347b33286c51b855821165448b..1f46c596e211e543c1fff7a40eb92b61015e8154 100644 (file)
@@ -10,6 +10,7 @@ use crate::{
   },
   DbPool,
 };
+use diesel::PgConnection;
 use lemmy_db::{naive_now, Bannable, Crud, Followable, Joinable, SortType};
 use lemmy_utils::{
   generate_actor_keypair,
@@ -34,7 +35,7 @@ pub struct GetCommunity {
 pub struct GetCommunityResponse {
   pub community: CommunityView,
   pub moderators: Vec<CommunityModeratorView>,
-  pub admins: Vec<UserView>,
+  pub admins: Vec<UserView>, // TODO this should be from GetSite, shouldn't need this
   pub online: usize,
 }
 
@@ -101,9 +102,21 @@ pub struct EditCommunity {
   title: String,
   description: Option<String>,
   category_id: i32,
-  removed: Option<bool>,
-  deleted: Option<bool>,
   nsfw: bool,
+  auth: String,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct DeleteCommunity {
+  pub edit_id: i32,
+  deleted: bool,
+  auth: String,
+}
+
+#[derive(Serialize, Deserialize)]
+pub struct RemoveCommunity {
+  pub edit_id: i32,
+  removed: bool,
   reason: Option<String>,
   expires: Option<i64>,
   auth: String,
@@ -366,24 +379,15 @@ impl Perform for Oper<EditCommunity> {
       return Err(APIError::err("site_ban").into());
     }
 
-    // Verify its a mod
+    // Verify its a mod (only mods can edit it)
     let edit_id = data.edit_id;
-    let mut editors: Vec<i32> = Vec::new();
-    editors.append(
-      &mut blocking(pool, move |conn| {
-        CommunityModeratorView::for_community(conn, edit_id)
-          .map(|v| v.into_iter().map(|m| m.user_id).collect())
-      })
-      .await??,
-    );
-    editors.append(
-      &mut blocking(pool, move |conn| {
-        UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())
-      })
-      .await??,
-    );
-    if !editors.contains(&user_id) {
-      return Err(APIError::err("no_community_edit_allowed").into());
+    let mods: Vec<i32> = blocking(pool, move |conn| {
+      CommunityModeratorView::for_community(conn, edit_id)
+        .map(|v| v.into_iter().map(|m| m.user_id).collect())
+    })
+    .await??;
+    if !mods.contains(&user_id) {
+      return Err(APIError::err("not_a_moderator").into());
     }
 
     let edit_id = data.edit_id;
@@ -395,8 +399,8 @@ impl Perform for Oper<EditCommunity> {
       description: data.description.to_owned(),
       category_id: data.category_id.to_owned(),
       creator_id: read_community.creator_id,
-      removed: data.removed.to_owned(),
-      deleted: data.deleted.to_owned(),
+      removed: Some(read_community.removed),
+      deleted: Some(read_community.deleted),
       nsfw: data.nsfw,
       updated: Some(naive_now()),
       actor_id: read_community.actor_id,
@@ -408,7 +412,7 @@ impl Perform for Oper<EditCommunity> {
     };
 
     let edit_id = data.edit_id;
-    let updated_community = match blocking(pool, move |conn| {
+    match blocking(pool, move |conn| {
       Community::update(conn, edit_id, &community_form)
     })
     .await?
@@ -417,42 +421,89 @@ impl Perform for Oper<EditCommunity> {
       Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
     };
 
-    // Mod tables
-    if let Some(removed) = data.removed.to_owned() {
-      let expires = match data.expires {
-        Some(time) => Some(naive_from_unix(time)),
-        None => None,
-      };
-      let form = ModRemoveCommunityForm {
-        mod_user_id: user_id,
+    // TODO there needs to be some kind of an apub update
+    // process for communities and users
+
+    let edit_id = data.edit_id;
+    let community_view = blocking(pool, move |conn| {
+      CommunityView::read(conn, edit_id, Some(user_id))
+    })
+    .await??;
+
+    let res = CommunityResponse {
+      community: community_view,
+    };
+
+    if let Some(ws) = websocket_info {
+      // Strip out the user id and subscribed when sending to others
+      let mut res_sent = res.clone();
+      res_sent.community.user_id = None;
+      res_sent.community.subscribed = None;
+
+      ws.chatserver.do_send(SendCommunityRoomMessage {
+        op: UserOperation::EditCommunity,
+        response: res_sent,
         community_id: data.edit_id,
-        removed: Some(removed),
-        reason: data.reason.to_owned(),
-        expires,
-      };
-      blocking(pool, move |conn| ModRemoveCommunity::create(conn, &form)).await??;
+        my_id: ws.id,
+      });
     }
 
-    if let Some(deleted) = data.deleted.to_owned() {
-      if deleted {
-        updated_community
-          .send_delete(&user, &self.client, pool)
-          .await?;
-      } else {
-        updated_community
-          .send_undo_delete(&user, &self.client, pool)
-          .await?;
-      }
-    } else if let Some(removed) = data.removed.to_owned() {
-      if removed {
-        updated_community
-          .send_remove(&user, &self.client, pool)
-          .await?;
-      } else {
-        updated_community
-          .send_undo_remove(&user, &self.client, pool)
-          .await?;
-      }
+    Ok(res)
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for Oper<DeleteCommunity> {
+  type Response = CommunityResponse;
+
+  async fn perform(
+    &self,
+    pool: &DbPool,
+    websocket_info: Option<WebsocketInfo>,
+  ) -> Result<CommunityResponse, LemmyError> {
+    let data: &DeleteCommunity = &self.data;
+
+    let claims = match Claims::decode(&data.auth) {
+      Ok(claims) => claims.claims,
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
+    };
+
+    let user_id = claims.id;
+
+    // Check for a site ban
+    let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+    if user.banned {
+      return Err(APIError::err("site_ban").into());
+    }
+
+    // Verify its the creator (only a creator can delete the community)
+    let edit_id = data.edit_id;
+    let read_community = blocking(pool, move |conn| Community::read(conn, edit_id)).await??;
+    if read_community.creator_id != user_id {
+      return Err(APIError::err("no_community_edit_allowed").into());
+    }
+
+    // Do the delete
+    let edit_id = data.edit_id;
+    let deleted = data.deleted;
+    let updated_community = match blocking(pool, move |conn| {
+      Community::update_deleted(conn, edit_id, deleted)
+    })
+    .await?
+    {
+      Ok(community) => community,
+      Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
+    };
+
+    // Send apub messages
+    if deleted {
+      updated_community
+        .send_delete(&user, &self.client, pool)
+        .await?;
+    } else {
+      updated_community
+        .send_undo_delete(&user, &self.client, pool)
+        .await?;
     }
 
     let edit_id = data.edit_id;
@@ -472,7 +523,105 @@ impl Perform for Oper<EditCommunity> {
       res_sent.community.subscribed = None;
 
       ws.chatserver.do_send(SendCommunityRoomMessage {
-        op: UserOperation::EditCommunity,
+        op: UserOperation::DeleteCommunity,
+        response: res_sent,
+        community_id: data.edit_id,
+        my_id: ws.id,
+      });
+    }
+
+    Ok(res)
+  }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for Oper<RemoveCommunity> {
+  type Response = CommunityResponse;
+
+  async fn perform(
+    &self,
+    pool: &DbPool,
+    websocket_info: Option<WebsocketInfo>,
+  ) -> Result<CommunityResponse, LemmyError> {
+    let data: &RemoveCommunity = &self.data;
+
+    let claims = match Claims::decode(&data.auth) {
+      Ok(claims) => claims.claims,
+      Err(_e) => return Err(APIError::err("not_logged_in").into()),
+    };
+
+    let user_id = claims.id;
+
+    // Check for a site ban
+    let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
+    if user.banned {
+      return Err(APIError::err("site_ban").into());
+    }
+
+    // Verify its an admin (only an admin can remove a community)
+    let admins: Vec<i32> = blocking(pool, move |conn| {
+      UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())
+    })
+    .await??;
+    if !admins.contains(&user_id) {
+      return Err(APIError::err("not_an_admin").into());
+    }
+
+    // Do the remove
+    let edit_id = data.edit_id;
+    let removed = data.removed;
+    let updated_community = match blocking(pool, move |conn| {
+      Community::update_removed(conn, edit_id, removed)
+    })
+    .await?
+    {
+      Ok(community) => community,
+      Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
+    };
+
+    // Mod tables
+    let expires = match data.expires {
+      Some(time) => Some(naive_from_unix(time)),
+      None => None,
+    };
+    let form = ModRemoveCommunityForm {
+      mod_user_id: user_id,
+      community_id: data.edit_id,
+      removed: Some(removed),
+      reason: data.reason.to_owned(),
+      expires,
+    };
+    blocking(pool, move |conn| ModRemoveCommunity::create(conn, &form)).await??;
+
+    // Apub messages
+    if removed {
+      updated_community
+        .send_remove(&user, &self.client, pool)
+        .await?;
+    } else {
+      updated_community
+        .send_undo_remove(&user, &self.client, pool)
+        .await?;
+    }
+
+    let edit_id = data.edit_id;
+    let community_view = blocking(pool, move |conn| {
+      CommunityView::read(conn, edit_id, Some(user_id))
+    })
+    .await??;
+
+    let res = CommunityResponse {
+      community: community_view,
+    };
+
+    if let Some(ws) = websocket_info {
+      // Strip out the user id and subscribed when sending to others
+      let mut res_sent = res.clone();
+      res_sent.community.user_id = None;
+      res_sent.community.subscribed = None;
+
+      ws.chatserver.do_send(SendCommunityRoomMessage {
+        op: UserOperation::RemoveCommunity,
         response: res_sent,
         community_id: data.edit_id,
         my_id: ws.id,
@@ -852,26 +1001,9 @@ impl Perform for Oper<TransferCommunity> {
       return Err(APIError::err("not_an_admin").into());
     }
 
-    let community_form = CommunityForm {
-      name: read_community.name,
-      title: read_community.title,
-      description: read_community.description,
-      category_id: read_community.category_id,
-      creator_id: data.user_id, // This makes the new user the community creator
-      removed: None,
-      deleted: None,
-      nsfw: read_community.nsfw,
-      updated: Some(naive_now()),
-      actor_id: read_community.actor_id,
-      local: read_community.local,
-      private_key: read_community.private_key,
-      public_key: read_community.public_key,
-      last_refreshed_at: None,
-      published: None,
-    };
-
     let community_id = data.community_id;
-    let update = move |conn: &'_ _| Community::update(conn, community_id, &community_form);
+    let new_creator = data.user_id;
+    let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator);
     if blocking(pool, update).await?.is_err() {
       return Err(APIError::err("couldnt_update_community").into());
     };
@@ -946,3 +1078,16 @@ impl Perform for Oper<TransferCommunity> {
     })
   }
 }
+
+pub fn community_mods_and_admins(
+  conn: &PgConnection,
+  community_id: i32,
+) -> Result<Vec<i32>, LemmyError> {
+  let mut editors: Vec<i32> = Vec::new();
+  editors.append(
+    &mut CommunityModeratorView::for_community(conn, community_id)
+      .map(|v| v.into_iter().map(|m| m.user_id).collect())?,
+  );
+  editors.append(&mut UserView::admins(conn).map(|v| v.into_iter().map(|a| a.id).collect())?);
+  Ok(editors)
+}
index a02f1d3b56529ab004d319eb9b95ef3a7928e51a..4722fb81f1ee149788713d7726fdffd6eef7e463 100644 (file)
@@ -53,7 +53,9 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
           .route("", web::put().to(route_post::<EditCommunity>))
           .route("/list", web::get().to(route_get::<ListCommunities>))
           .route("/follow", web::post().to(route_post::<FollowCommunity>))
+          .route("/delete", web::post().to(route_post::<DeleteCommunity>))
           // Mod Actions
+          .route("/remove", web::post().to(route_post::<RemoveCommunity>))
           .route("/transfer", web::post().to(route_post::<TransferCommunity>))
           .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
           .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
index 431273d2564d85808372a3936bd6a153fe4c2956..c4c0214632267fca3cfa6e867510d6cc6973f5b5 100644 (file)
@@ -35,6 +35,8 @@ pub enum UserOperation {
   EditPost,
   SavePost,
   EditCommunity,
+  DeleteCommunity,
+  RemoveCommunity,
   FollowCommunity,
   GetFollowedCommunities,
   GetUserDetails,
index 4909908443929b720a0d5099194db409274a8045..0344e1b99315fe0eb08a53b39dd63fe9043a1453 100644 (file)
@@ -212,6 +212,9 @@ impl ChatServer {
 
     // Also leave all communities
     // This avoids double messages
+    // TODO found a bug, whereby community messages like
+    // delete and remove aren't sent, because
+    // you left the community room
     for sessions in self.community_rooms.values_mut() {
       sessions.remove(&id);
     }
@@ -483,6 +486,8 @@ impl ChatServer {
         UserOperation::ListCommunities => do_user_operation::<ListCommunities>(args).await,
         UserOperation::CreateCommunity => do_user_operation::<CreateCommunity>(args).await,
         UserOperation::EditCommunity => do_user_operation::<EditCommunity>(args).await,
+        UserOperation::DeleteCommunity => do_user_operation::<DeleteCommunity>(args).await,
+        UserOperation::RemoveCommunity => do_user_operation::<RemoveCommunity>(args).await,
         UserOperation::FollowCommunity => do_user_operation::<FollowCommunity>(args).await,
         UserOperation::GetFollowedCommunities => {
           do_user_operation::<GetFollowedCommunities>(args).await
index 09454b15ca4ecf04eda5f42364d86df83a8a624b..891654b28a0cd86bb0cae945b3eb6e1255c9be30 100644 (file)
@@ -13,6 +13,8 @@ import {
   CommentForm,
   CommentResponse,
   CommunityForm,
+  DeleteCommunityForm,
+  RemoveCommunityForm,
   GetCommunityResponse,
   CommentLikeForm,
   CreatePostLikeForm,
@@ -731,20 +733,16 @@ describe('main', () => {
       expect(getPostResAgainTwo.post.deleted).toBe(false);
 
       // lemmy_beta deletes the community
-      let deleteCommunityForm: CommunityForm = {
-        name: communityName,
-        title: communityName,
-        category_id: 1,
+      let deleteCommunityForm: DeleteCommunityForm = {
         edit_id: createCommunityRes.community.id,
-        nsfw: false,
         deleted: true,
         auth: lemmyBetaAuth,
       };
 
       let deleteResponse: CommunityResponse = await fetch(
-        `${lemmyBetaApiUrl}/community`,
+        `${lemmyBetaApiUrl}/community/delete`,
         {
-          method: 'PUT',
+          method: 'POST',
           headers: {
             'Content-Type': 'application/json',
           },
@@ -764,20 +762,16 @@ describe('main', () => {
       expect(getCommunityRes.community.deleted).toBe(true);
 
       // lemmy_beta undeletes the community
-      let undeleteCommunityForm: CommunityForm = {
-        name: communityName,
-        title: communityName,
-        category_id: 1,
+      let undeleteCommunityForm: DeleteCommunityForm = {
         edit_id: createCommunityRes.community.id,
-        nsfw: false,
         deleted: false,
         auth: lemmyBetaAuth,
       };
 
       let undeleteCommunityRes: CommunityResponse = await fetch(
-        `${lemmyBetaApiUrl}/community`,
+        `${lemmyBetaApiUrl}/community/delete`,
         {
-          method: 'PUT',
+          method: 'POST',
           headers: {
             'Content-Type': 'application/json',
           },
@@ -1006,21 +1000,17 @@ describe('main', () => {
       }).then(d => d.json());
       expect(getPostResAgainTwo.post.removed).toBe(false);
 
-      // lemmy_beta deletes the community
-      let removeCommunityForm: CommunityForm = {
-        name: communityName,
-        title: communityName,
-        category_id: 1,
+      // lemmy_beta removes the community
+      let removeCommunityForm: RemoveCommunityForm = {
         edit_id: createCommunityRes.community.id,
-        nsfw: false,
         removed: true,
         auth: lemmyBetaAuth,
       };
 
       let removeCommunityRes: CommunityResponse = await fetch(
-        `${lemmyBetaApiUrl}/community`,
+        `${lemmyBetaApiUrl}/community/remove`,
         {
-          method: 'PUT',
+          method: 'POST',
           headers: {
             'Content-Type': 'application/json',
           },
@@ -1028,7 +1018,7 @@ describe('main', () => {
         }
       ).then(d => d.json());
 
-      // Make sure the delete went through
+      // Make sure the remove went through
       expect(removeCommunityRes.community.removed).toBe(true);
 
       // Re-get it from alpha, make sure its removed there too
@@ -1040,20 +1030,16 @@ describe('main', () => {
       expect(getCommunityRes.community.removed).toBe(true);
 
       // lemmy_beta unremoves the community
-      let unremoveCommunityForm: CommunityForm = {
-        name: communityName,
-        title: communityName,
-        category_id: 1,
+      let unremoveCommunityForm: RemoveCommunityForm = {
         edit_id: createCommunityRes.community.id,
-        nsfw: false,
         removed: false,
         auth: lemmyBetaAuth,
       };
 
       let unremoveCommunityRes: CommunityResponse = await fetch(
-        `${lemmyBetaApiUrl}/community`,
+        `${lemmyBetaApiUrl}/community/remove`,
         {
-          method: 'PUT',
+          method: 'POST',
           headers: {
             'Content-Type': 'application/json',
           },
index 99b692cacf96694740d3bca8327278fae481328a..2899c2cb67e8aac8e3bd86ea6824126db7b0c6b3 100644 (file)
@@ -360,7 +360,11 @@ export class Community extends Component<any, State> {
       document.title = `/c/${this.state.community.name} - ${this.state.site.name}`;
       this.setState(this.state);
       this.fetchData();
-    } else if (res.op == UserOperation.EditCommunity) {
+    } else if (
+      res.op == UserOperation.EditCommunity ||
+      res.op == UserOperation.DeleteCommunity ||
+      res.op == UserOperation.RemoveCommunity
+    ) {
       let data = res.data as CommunityResponse;
       this.state.community = data.community;
       this.setState(this.state);
index 9eef286c9744cb5fea34aa4c91e1e03cb8da447d..97f80b6e680540adc83e4c878a53b130b4cc9a33 100644 (file)
@@ -462,7 +462,11 @@ export class Post extends Component<any, PostState> {
       this.state.post = data.post;
       this.setState(this.state);
       setupTippy();
-    } else if (res.op == UserOperation.EditCommunity) {
+    } else if (
+      res.op == UserOperation.EditCommunity ||
+      res.op == UserOperation.DeleteCommunity ||
+      res.op == UserOperation.RemoveCommunity
+    ) {
       let data = res.data as CommunityResponse;
       this.state.community = data.community;
       this.state.post.community_id = data.community.id;
index 42abf65aab67626b0b15d59847f7d343adc85d5f..b600628f0fe564c0624abedaaf395a4418006e06 100644 (file)
@@ -4,7 +4,8 @@ import {
   Community,
   CommunityUser,
   FollowCommunityForm,
-  CommunityForm as CommunityFormI,
+  DeleteCommunityForm,
+  RemoveCommunityForm,
   UserView,
 } from '../interfaces';
 import { WebSocketService, UserService } from '../services';
@@ -284,16 +285,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
 
   handleDeleteClick(i: Sidebar) {
     event.preventDefault();
-    let deleteForm: CommunityFormI = {
-      name: i.props.community.name,
-      title: i.props.community.title,
-      category_id: i.props.community.category_id,
+    let deleteForm: DeleteCommunityForm = {
       edit_id: i.props.community.id,
       deleted: !i.props.community.deleted,
-      nsfw: i.props.community.nsfw,
-      auth: null,
     };
-    WebSocketService.Instance.editCommunity(deleteForm);
+    WebSocketService.Instance.deleteCommunity(deleteForm);
   }
 
   handleUnsubscribe(communityId: number) {
@@ -350,18 +346,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
 
   handleModRemoveSubmit(i: Sidebar) {
     event.preventDefault();
-    let deleteForm: CommunityFormI = {
-      name: i.props.community.name,
-      title: i.props.community.title,
-      category_id: i.props.community.category_id,
+    let removeForm: RemoveCommunityForm = {
       edit_id: i.props.community.id,
       removed: !i.props.community.removed,
       reason: i.state.removeReason,
       expires: getUnixTime(i.state.removeExpires),
-      nsfw: i.props.community.nsfw,
-      auth: null,
     };
-    WebSocketService.Instance.editCommunity(deleteForm);
+    WebSocketService.Instance.removeCommunity(removeForm);
 
     i.state.showRemoveDialog = false;
     i.setState(i.state);
index 0beb0ff92bf5b4fad820773b9499eea58d45a78c..7f650f1b147ee479b820c2f2e999d4122312f41b 100644 (file)
@@ -16,6 +16,8 @@ export enum UserOperation {
   EditPost,
   SavePost,
   EditCommunity,
+  DeleteCommunity,
+  RemoveCommunity,
   FollowCommunity,
   GetFollowedCommunities,
   GetUserDetails,
@@ -573,13 +575,23 @@ export interface UserSettingsForm {
 
 export interface CommunityForm {
   name: string;
+  edit_id?: number;
   title: string;
   description?: string;
   category_id: number;
-  edit_id?: number;
-  removed?: boolean;
-  deleted?: boolean;
   nsfw: boolean;
+  auth?: string;
+}
+
+export interface DeleteCommunityForm {
+  edit_id: number;
+  deleted: boolean;
+  auth?: string;
+}
+
+export interface RemoveCommunityForm {
+  edit_id: number;
+  removed: boolean;
   reason?: string;
   expires?: number;
   auth?: string;
@@ -879,6 +891,8 @@ export type MessageType =
   | LoginForm
   | RegisterForm
   | CommunityForm
+  | DeleteCommunityForm
+  | RemoveCommunityForm
   | FollowCommunityForm
   | ListCommunitiesForm
   | GetFollowedCommunitiesForm
index 54dc96359d020595e3c5925babf5279d7d628303..26e58135d0a0f5da0f75d4ec6eb98bac83aaf428 100644 (file)
@@ -4,6 +4,8 @@ import {
   RegisterForm,
   UserOperation,
   CommunityForm,
+  DeleteCommunityForm,
+  RemoveCommunityForm,
   PostForm,
   SavePostForm,
   CommentForm,
@@ -105,18 +107,24 @@ export class WebSocketService {
     this.ws.send(this.wsSendWrapper(UserOperation.Register, registerForm));
   }
 
-  public createCommunity(communityForm: CommunityForm) {
-    this.setAuth(communityForm);
-    this.ws.send(
-      this.wsSendWrapper(UserOperation.CreateCommunity, communityForm)
-    );
+  public createCommunity(form: CommunityForm) {
+    this.setAuth(form);
+    this.ws.send(this.wsSendWrapper(UserOperation.CreateCommunity, form));
   }
 
-  public editCommunity(communityForm: CommunityForm) {
-    this.setAuth(communityForm);
-    this.ws.send(
-      this.wsSendWrapper(UserOperation.EditCommunity, communityForm)
-    );
+  public editCommunity(form: CommunityForm) {
+    this.setAuth(form);
+    this.ws.send(this.wsSendWrapper(UserOperation.EditCommunity, form));
+  }
+
+  public deleteCommunity(form: DeleteCommunityForm) {
+    this.setAuth(form);
+    this.ws.send(this.wsSendWrapper(UserOperation.DeleteCommunity, form));
+  }
+
+  public removeCommunity(form: RemoveCommunityForm) {
+    this.setAuth(form);
+    this.ws.send(this.wsSendWrapper(UserOperation.RemoveCommunity, form));
   }
 
   public followCommunity(followCommunityForm: FollowCommunityForm) {
index e9d768f2f5de4ca4521447fc091eaa49ea5d4b47..8ac99c26f8801edf88de39f5640b30818e986ed3 100644 (file)
     "couldnt_save_post": "Couldn't save post.",
     "no_slurs": "No slurs.",
     "not_an_admin": "Not an admin.",
+    "not_a_moderator": "Not a moderator.",
     "site_already_exists": "Site already exists.",
     "couldnt_update_site": "Couldn't update site.",
     "couldnt_find_that_username_or_email":