From 9bc6698f5841e3c16a84a0fd35f8383a9310b012 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 20 Jul 2020 13:37:39 -0400 Subject: [PATCH] Added community delete and remove. --- docs/src/contributing_websocket_http_api.md | 62 +++- server/lemmy_db/src/community.rs | 33 +++ server/lemmy_db/src/community_view.rs | 8 +- server/src/api/community.rs | 303 +++++++++++++++----- server/src/routes/api.rs | 2 + server/src/websocket/mod.rs | 2 + server/src/websocket/server.rs | 5 + ui/src/api_tests/api.spec.ts | 46 ++- ui/src/components/community.tsx | 6 +- ui/src/components/post.tsx | 6 +- ui/src/components/sidebar.tsx | 21 +- ui/src/interfaces.ts | 20 +- ui/src/services/WebSocketService.ts | 28 +- ui/translations/en.json | 1 + 14 files changed, 395 insertions(+), 148 deletions(-) diff --git a/docs/src/contributing_websocket_http_api.md b/docs/src/contributing_websocket_http_api.md index 63d8f994b..4931ed583 100644 --- a/docs/src/contributing_websocket_http_api.md +++ b/docs/src/contributing_websocket_http_api.md @@ -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, category_id: i32, - removed: Option, - deleted: Option, - reason: Option, - expires: Option, 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, + expires: Option, + auth: String, + } +} +``` +##### Response +```rust +{ + op: "RemoveCommunity", + data: { + community: CommunityView + } +} +``` +##### HTTP + +`POST /community/remove` + #### Follow Community ##### Request ```rust diff --git a/server/lemmy_db/src/community.rs b/server/lemmy_db/src/community.rs index e1f243919..4fe507f72 100644 --- a/server/lemmy_db/src/community.rs +++ b/server/lemmy_db/src/community.rs @@ -99,6 +99,39 @@ impl Community { use crate::schema::community::dsl::*; community.filter(local.eq(true)).load::(conn) } + + pub fn update_deleted( + conn: &PgConnection, + community_id: i32, + new_deleted: bool, + ) -> Result { + use crate::schema::community::dsl::*; + diesel::update(community.find(community_id)) + .set(deleted.eq(new_deleted)) + .get_result::(conn) + } + + pub fn update_removed( + conn: &PgConnection, + community_id: i32, + new_removed: bool, + ) -> Result { + use crate::schema::community::dsl::*; + diesel::update(community.find(community_id)) + .set(removed.eq(new_removed)) + .get_result::(conn) + } + + pub fn update_creator( + conn: &PgConnection, + community_id: i32, + new_creator_id: i32, + ) -> Result { + use crate::schema::community::dsl::*; + diesel::update(community.find(community_id)) + .set(creator_id.eq(new_creator_id)) + .get_result::(conn) + } } #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] diff --git a/server/lemmy_db/src/community_view.rs b/server/lemmy_db/src/community_view.rs index 5c6bd81a1..880c94559 100644 --- a/server/lemmy_db/src/community_view.rs +++ b/server/lemmy_db/src/community_view.rs @@ -295,18 +295,18 @@ pub struct CommunityModeratorView { } impl CommunityModeratorView { - pub fn for_community(conn: &PgConnection, from_community_id: i32) -> Result, Error> { + pub fn for_community(conn: &PgConnection, for_community_id: i32) -> Result, 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::(conn) } - pub fn for_user(conn: &PgConnection, from_user_id: i32) -> Result, Error> { + pub fn for_user(conn: &PgConnection, for_user_id: i32) -> Result, 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::(conn) } diff --git a/server/src/api/community.rs b/server/src/api/community.rs index fc5cb0e61..1f46c596e 100644 --- a/server/src/api/community.rs +++ b/server/src/api/community.rs @@ -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, - pub admins: Vec, + pub admins: Vec, // TODO this should be from GetSite, shouldn't need this pub online: usize, } @@ -101,9 +102,21 @@ pub struct EditCommunity { title: String, description: Option, category_id: i32, - removed: Option, - deleted: Option, 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, expires: Option, auth: String, @@ -366,24 +379,15 @@ impl Perform for Oper { 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 = 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 = 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 { 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 { }; 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,43 +421,8 @@ impl Perform for Oper { 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, - community_id: data.edit_id, - removed: Some(removed), - reason: data.reason.to_owned(), - expires, - }; - blocking(pool, move |conn| ModRemoveCommunity::create(conn, &form)).await??; - } - - 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?; - } - } + // 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| { @@ -483,6 +452,186 @@ impl Perform for Oper { } } +#[async_trait::async_trait(?Send)] +impl Perform for Oper { + type Response = CommunityResponse; + + async fn perform( + &self, + pool: &DbPool, + websocket_info: Option, + ) -> Result { + 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; + 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::DeleteCommunity, + response: res_sent, + community_id: data.edit_id, + my_id: ws.id, + }); + } + + Ok(res) + } +} + +#[async_trait::async_trait(?Send)] +impl Perform for Oper { + type Response = CommunityResponse; + + async fn perform( + &self, + pool: &DbPool, + websocket_info: Option, + ) -> Result { + 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 = 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, + }); + } + + Ok(res) + } +} + #[async_trait::async_trait(?Send)] impl Perform for Oper { type Response = ListCommunitiesResponse; @@ -852,26 +1001,9 @@ impl Perform for Oper { 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 { }) } } + +pub fn community_mods_and_admins( + conn: &PgConnection, + community_id: i32, +) -> Result, LemmyError> { + let mut editors: Vec = 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) +} diff --git a/server/src/routes/api.rs b/server/src/routes/api.rs index a02f1d3b5..4722fb81f 100644 --- a/server/src/routes/api.rs +++ b/server/src/routes/api.rs @@ -53,7 +53,9 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) { .route("", web::put().to(route_post::)) .route("/list", web::get().to(route_get::)) .route("/follow", web::post().to(route_post::)) + .route("/delete", web::post().to(route_post::)) // Mod Actions + .route("/remove", web::post().to(route_post::)) .route("/transfer", web::post().to(route_post::)) .route("/ban_user", web::post().to(route_post::)) .route("/mod", web::post().to(route_post::)), diff --git a/server/src/websocket/mod.rs b/server/src/websocket/mod.rs index 431273d25..c4c021463 100644 --- a/server/src/websocket/mod.rs +++ b/server/src/websocket/mod.rs @@ -35,6 +35,8 @@ pub enum UserOperation { EditPost, SavePost, EditCommunity, + DeleteCommunity, + RemoveCommunity, FollowCommunity, GetFollowedCommunities, GetUserDetails, diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index 490990844..0344e1b99 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -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::(args).await, UserOperation::CreateCommunity => do_user_operation::(args).await, UserOperation::EditCommunity => do_user_operation::(args).await, + UserOperation::DeleteCommunity => do_user_operation::(args).await, + UserOperation::RemoveCommunity => do_user_operation::(args).await, UserOperation::FollowCommunity => do_user_operation::(args).await, UserOperation::GetFollowedCommunities => { do_user_operation::(args).await diff --git a/ui/src/api_tests/api.spec.ts b/ui/src/api_tests/api.spec.ts index 09454b15c..891654b28 100644 --- a/ui/src/api_tests/api.spec.ts +++ b/ui/src/api_tests/api.spec.ts @@ -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', }, diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx index 99b692cac..2899c2cb6 100644 --- a/ui/src/components/community.tsx +++ b/ui/src/components/community.tsx @@ -360,7 +360,11 @@ export class Community extends Component { 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); diff --git a/ui/src/components/post.tsx b/ui/src/components/post.tsx index 9eef286c9..97f80b6e6 100644 --- a/ui/src/components/post.tsx +++ b/ui/src/components/post.tsx @@ -462,7 +462,11 @@ export class Post extends Component { 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; diff --git a/ui/src/components/sidebar.tsx b/ui/src/components/sidebar.tsx index 42abf65aa..b600628f0 100644 --- a/ui/src/components/sidebar.tsx +++ b/ui/src/components/sidebar.tsx @@ -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 { 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 { 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); diff --git a/ui/src/interfaces.ts b/ui/src/interfaces.ts index 0beb0ff92..7f650f1b1 100644 --- a/ui/src/interfaces.ts +++ b/ui/src/interfaces.ts @@ -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 diff --git a/ui/src/services/WebSocketService.ts b/ui/src/services/WebSocketService.ts index 54dc96359..26e58135d 100644 --- a/ui/src/services/WebSocketService.ts +++ b/ui/src/services/WebSocketService.ts @@ -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) { diff --git a/ui/translations/en.json b/ui/translations/en.json index e9d768f2f..8ac99c26f 100644 --- a/ui/translations/en.json +++ b/ui/translations/en.json @@ -254,6 +254,7 @@ "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":