Added community delete and remove.

This commit is contained in:
Dessalines 2020-07-20 13:37:39 -04:00
parent a67f46bec5
commit 9bc6698f58
14 changed files with 395 additions and 148 deletions

View file

@ -1102,7 +1102,7 @@ Search types are `All, Comments, Posts, Communities, Users, Url`
`POST /community/mod` `POST /community/mod`
#### Edit Community #### Edit Community
Mods and admins can remove and lock a community, creators can delete it. Only mods can edit a community.
##### Request ##### Request
```rust ```rust
@ -1113,10 +1113,6 @@ Mods and admins can remove and lock a community, creators can delete it.
title: String, title: String,
description: Option<String>, description: Option<String>,
category_id: i32, category_id: i32,
removed: Option<bool>,
deleted: Option<bool>,
reason: Option<String>,
expires: Option<i64>,
auth: String auth: String
} }
} }
@ -1134,6 +1130,62 @@ Mods and admins can remove and lock a community, creators can delete it.
`PUT /community` `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 #### Follow Community
##### Request ##### Request
```rust ```rust

View file

@ -99,6 +99,39 @@ impl Community {
use crate::schema::community::dsl::*; use crate::schema::community::dsl::*;
community.filter(local.eq(true)).load::<Community>(conn) 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)] #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]

View file

@ -295,18 +295,18 @@ pub struct CommunityModeratorView {
} }
impl 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::*; use super::community_view::community_moderator_view::dsl::*;
community_moderator_view community_moderator_view
.filter(community_id.eq(from_community_id)) .filter(community_id.eq(for_community_id))
.order_by(published) .order_by(published)
.load::<Self>(conn) .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::*; use super::community_view::community_moderator_view::dsl::*;
community_moderator_view community_moderator_view
.filter(user_id.eq(from_user_id)) .filter(user_id.eq(for_user_id))
.order_by(published) .order_by(published)
.load::<Self>(conn) .load::<Self>(conn)
} }

View file

@ -10,6 +10,7 @@ use crate::{
}, },
DbPool, DbPool,
}; };
use diesel::PgConnection;
use lemmy_db::{naive_now, Bannable, Crud, Followable, Joinable, SortType}; use lemmy_db::{naive_now, Bannable, Crud, Followable, Joinable, SortType};
use lemmy_utils::{ use lemmy_utils::{
generate_actor_keypair, generate_actor_keypair,
@ -34,7 +35,7 @@ pub struct GetCommunity {
pub struct GetCommunityResponse { pub struct GetCommunityResponse {
pub community: CommunityView, pub community: CommunityView,
pub moderators: Vec<CommunityModeratorView>, 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, pub online: usize,
} }
@ -101,9 +102,21 @@ pub struct EditCommunity {
title: String, title: String,
description: Option<String>, description: Option<String>,
category_id: i32, category_id: i32,
removed: Option<bool>,
deleted: Option<bool>,
nsfw: 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>, reason: Option<String>,
expires: Option<i64>, expires: Option<i64>,
auth: String, auth: String,
@ -366,24 +379,15 @@ impl Perform for Oper<EditCommunity> {
return Err(APIError::err("site_ban").into()); 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 edit_id = data.edit_id;
let mut editors: Vec<i32> = Vec::new(); let mods: Vec<i32> = blocking(pool, move |conn| {
editors.append( CommunityModeratorView::for_community(conn, edit_id)
&mut blocking(pool, move |conn| { .map(|v| v.into_iter().map(|m| m.user_id).collect())
CommunityModeratorView::for_community(conn, edit_id) })
.map(|v| v.into_iter().map(|m| m.user_id).collect()) .await??;
}) if !mods.contains(&user_id) {
.await??, return Err(APIError::err("not_a_moderator").into());
);
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 edit_id = data.edit_id; let edit_id = data.edit_id;
@ -395,8 +399,8 @@ impl Perform for Oper<EditCommunity> {
description: data.description.to_owned(), description: data.description.to_owned(),
category_id: data.category_id.to_owned(), category_id: data.category_id.to_owned(),
creator_id: read_community.creator_id, creator_id: read_community.creator_id,
removed: data.removed.to_owned(), removed: Some(read_community.removed),
deleted: data.deleted.to_owned(), deleted: Some(read_community.deleted),
nsfw: data.nsfw, nsfw: data.nsfw,
updated: Some(naive_now()), updated: Some(naive_now()),
actor_id: read_community.actor_id, actor_id: read_community.actor_id,
@ -408,7 +412,7 @@ impl Perform for Oper<EditCommunity> {
}; };
let edit_id = data.edit_id; 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) Community::update(conn, edit_id, &community_form)
}) })
.await? .await?
@ -417,43 +421,8 @@ impl Perform for Oper<EditCommunity> {
Err(_e) => return Err(APIError::err("couldnt_update_community").into()), Err(_e) => return Err(APIError::err("couldnt_update_community").into()),
}; };
// Mod tables // TODO there needs to be some kind of an apub update
if let Some(removed) = data.removed.to_owned() { // process for communities and users
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?;
}
}
let edit_id = data.edit_id; let edit_id = data.edit_id;
let community_view = blocking(pool, move |conn| { let community_view = blocking(pool, move |conn| {
@ -483,6 +452,186 @@ impl Perform for Oper<EditCommunity> {
} }
} }
#[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;
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<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,
});
}
Ok(res)
}
}
#[async_trait::async_trait(?Send)] #[async_trait::async_trait(?Send)]
impl Perform for Oper<ListCommunities> { impl Perform for Oper<ListCommunities> {
type Response = ListCommunitiesResponse; type Response = ListCommunitiesResponse;
@ -852,26 +1001,9 @@ impl Perform for Oper<TransferCommunity> {
return Err(APIError::err("not_an_admin").into()); 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 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() { if blocking(pool, update).await?.is_err() {
return Err(APIError::err("couldnt_update_community").into()); 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)
}

View file

@ -53,7 +53,9 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
.route("", web::put().to(route_post::<EditCommunity>)) .route("", web::put().to(route_post::<EditCommunity>))
.route("/list", web::get().to(route_get::<ListCommunities>)) .route("/list", web::get().to(route_get::<ListCommunities>))
.route("/follow", web::post().to(route_post::<FollowCommunity>)) .route("/follow", web::post().to(route_post::<FollowCommunity>))
.route("/delete", web::post().to(route_post::<DeleteCommunity>))
// Mod Actions // Mod Actions
.route("/remove", web::post().to(route_post::<RemoveCommunity>))
.route("/transfer", web::post().to(route_post::<TransferCommunity>)) .route("/transfer", web::post().to(route_post::<TransferCommunity>))
.route("/ban_user", web::post().to(route_post::<BanFromCommunity>)) .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
.route("/mod", web::post().to(route_post::<AddModToCommunity>)), .route("/mod", web::post().to(route_post::<AddModToCommunity>)),

View file

@ -35,6 +35,8 @@ pub enum UserOperation {
EditPost, EditPost,
SavePost, SavePost,
EditCommunity, EditCommunity,
DeleteCommunity,
RemoveCommunity,
FollowCommunity, FollowCommunity,
GetFollowedCommunities, GetFollowedCommunities,
GetUserDetails, GetUserDetails,

View file

@ -212,6 +212,9 @@ impl ChatServer {
// Also leave all communities // Also leave all communities
// This avoids double messages // 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() { for sessions in self.community_rooms.values_mut() {
sessions.remove(&id); sessions.remove(&id);
} }
@ -483,6 +486,8 @@ impl ChatServer {
UserOperation::ListCommunities => do_user_operation::<ListCommunities>(args).await, UserOperation::ListCommunities => do_user_operation::<ListCommunities>(args).await,
UserOperation::CreateCommunity => do_user_operation::<CreateCommunity>(args).await, UserOperation::CreateCommunity => do_user_operation::<CreateCommunity>(args).await,
UserOperation::EditCommunity => do_user_operation::<EditCommunity>(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::FollowCommunity => do_user_operation::<FollowCommunity>(args).await,
UserOperation::GetFollowedCommunities => { UserOperation::GetFollowedCommunities => {
do_user_operation::<GetFollowedCommunities>(args).await do_user_operation::<GetFollowedCommunities>(args).await

View file

@ -13,6 +13,8 @@ import {
CommentForm, CommentForm,
CommentResponse, CommentResponse,
CommunityForm, CommunityForm,
DeleteCommunityForm,
RemoveCommunityForm,
GetCommunityResponse, GetCommunityResponse,
CommentLikeForm, CommentLikeForm,
CreatePostLikeForm, CreatePostLikeForm,
@ -731,20 +733,16 @@ describe('main', () => {
expect(getPostResAgainTwo.post.deleted).toBe(false); expect(getPostResAgainTwo.post.deleted).toBe(false);
// lemmy_beta deletes the community // lemmy_beta deletes the community
let deleteCommunityForm: CommunityForm = { let deleteCommunityForm: DeleteCommunityForm = {
name: communityName,
title: communityName,
category_id: 1,
edit_id: createCommunityRes.community.id, edit_id: createCommunityRes.community.id,
nsfw: false,
deleted: true, deleted: true,
auth: lemmyBetaAuth, auth: lemmyBetaAuth,
}; };
let deleteResponse: CommunityResponse = await fetch( let deleteResponse: CommunityResponse = await fetch(
`${lemmyBetaApiUrl}/community`, `${lemmyBetaApiUrl}/community/delete`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@ -764,20 +762,16 @@ describe('main', () => {
expect(getCommunityRes.community.deleted).toBe(true); expect(getCommunityRes.community.deleted).toBe(true);
// lemmy_beta undeletes the community // lemmy_beta undeletes the community
let undeleteCommunityForm: CommunityForm = { let undeleteCommunityForm: DeleteCommunityForm = {
name: communityName,
title: communityName,
category_id: 1,
edit_id: createCommunityRes.community.id, edit_id: createCommunityRes.community.id,
nsfw: false,
deleted: false, deleted: false,
auth: lemmyBetaAuth, auth: lemmyBetaAuth,
}; };
let undeleteCommunityRes: CommunityResponse = await fetch( let undeleteCommunityRes: CommunityResponse = await fetch(
`${lemmyBetaApiUrl}/community`, `${lemmyBetaApiUrl}/community/delete`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@ -1006,21 +1000,17 @@ describe('main', () => {
}).then(d => d.json()); }).then(d => d.json());
expect(getPostResAgainTwo.post.removed).toBe(false); expect(getPostResAgainTwo.post.removed).toBe(false);
// lemmy_beta deletes the community // lemmy_beta removes the community
let removeCommunityForm: CommunityForm = { let removeCommunityForm: RemoveCommunityForm = {
name: communityName,
title: communityName,
category_id: 1,
edit_id: createCommunityRes.community.id, edit_id: createCommunityRes.community.id,
nsfw: false,
removed: true, removed: true,
auth: lemmyBetaAuth, auth: lemmyBetaAuth,
}; };
let removeCommunityRes: CommunityResponse = await fetch( let removeCommunityRes: CommunityResponse = await fetch(
`${lemmyBetaApiUrl}/community`, `${lemmyBetaApiUrl}/community/remove`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
@ -1028,7 +1018,7 @@ describe('main', () => {
} }
).then(d => d.json()); ).then(d => d.json());
// Make sure the delete went through // Make sure the remove went through
expect(removeCommunityRes.community.removed).toBe(true); expect(removeCommunityRes.community.removed).toBe(true);
// Re-get it from alpha, make sure its removed there too // Re-get it from alpha, make sure its removed there too
@ -1040,20 +1030,16 @@ describe('main', () => {
expect(getCommunityRes.community.removed).toBe(true); expect(getCommunityRes.community.removed).toBe(true);
// lemmy_beta unremoves the community // lemmy_beta unremoves the community
let unremoveCommunityForm: CommunityForm = { let unremoveCommunityForm: RemoveCommunityForm = {
name: communityName,
title: communityName,
category_id: 1,
edit_id: createCommunityRes.community.id, edit_id: createCommunityRes.community.id,
nsfw: false,
removed: false, removed: false,
auth: lemmyBetaAuth, auth: lemmyBetaAuth,
}; };
let unremoveCommunityRes: CommunityResponse = await fetch( let unremoveCommunityRes: CommunityResponse = await fetch(
`${lemmyBetaApiUrl}/community`, `${lemmyBetaApiUrl}/community/remove`,
{ {
method: 'PUT', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },

View file

@ -360,7 +360,11 @@ export class Community extends Component<any, State> {
document.title = `/c/${this.state.community.name} - ${this.state.site.name}`; document.title = `/c/${this.state.community.name} - ${this.state.site.name}`;
this.setState(this.state); this.setState(this.state);
this.fetchData(); 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; let data = res.data as CommunityResponse;
this.state.community = data.community; this.state.community = data.community;
this.setState(this.state); this.setState(this.state);

View file

@ -462,7 +462,11 @@ export class Post extends Component<any, PostState> {
this.state.post = data.post; this.state.post = data.post;
this.setState(this.state); this.setState(this.state);
setupTippy(); 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; let data = res.data as CommunityResponse;
this.state.community = data.community; this.state.community = data.community;
this.state.post.community_id = data.community.id; this.state.post.community_id = data.community.id;

View file

@ -4,7 +4,8 @@ import {
Community, Community,
CommunityUser, CommunityUser,
FollowCommunityForm, FollowCommunityForm,
CommunityForm as CommunityFormI, DeleteCommunityForm,
RemoveCommunityForm,
UserView, UserView,
} from '../interfaces'; } from '../interfaces';
import { WebSocketService, UserService } from '../services'; import { WebSocketService, UserService } from '../services';
@ -284,16 +285,11 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
handleDeleteClick(i: Sidebar) { handleDeleteClick(i: Sidebar) {
event.preventDefault(); event.preventDefault();
let deleteForm: CommunityFormI = { let deleteForm: DeleteCommunityForm = {
name: i.props.community.name,
title: i.props.community.title,
category_id: i.props.community.category_id,
edit_id: i.props.community.id, edit_id: i.props.community.id,
deleted: !i.props.community.deleted, deleted: !i.props.community.deleted,
nsfw: i.props.community.nsfw,
auth: null,
}; };
WebSocketService.Instance.editCommunity(deleteForm); WebSocketService.Instance.deleteCommunity(deleteForm);
} }
handleUnsubscribe(communityId: number) { handleUnsubscribe(communityId: number) {
@ -350,18 +346,13 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
handleModRemoveSubmit(i: Sidebar) { handleModRemoveSubmit(i: Sidebar) {
event.preventDefault(); event.preventDefault();
let deleteForm: CommunityFormI = { let removeForm: RemoveCommunityForm = {
name: i.props.community.name,
title: i.props.community.title,
category_id: i.props.community.category_id,
edit_id: i.props.community.id, edit_id: i.props.community.id,
removed: !i.props.community.removed, removed: !i.props.community.removed,
reason: i.state.removeReason, reason: i.state.removeReason,
expires: getUnixTime(i.state.removeExpires), 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.state.showRemoveDialog = false;
i.setState(i.state); i.setState(i.state);

20
ui/src/interfaces.ts vendored
View file

@ -16,6 +16,8 @@ export enum UserOperation {
EditPost, EditPost,
SavePost, SavePost,
EditCommunity, EditCommunity,
DeleteCommunity,
RemoveCommunity,
FollowCommunity, FollowCommunity,
GetFollowedCommunities, GetFollowedCommunities,
GetUserDetails, GetUserDetails,
@ -573,13 +575,23 @@ export interface UserSettingsForm {
export interface CommunityForm { export interface CommunityForm {
name: string; name: string;
edit_id?: number;
title: string; title: string;
description?: string; description?: string;
category_id: number; category_id: number;
edit_id?: number;
removed?: boolean;
deleted?: boolean;
nsfw: 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; reason?: string;
expires?: number; expires?: number;
auth?: string; auth?: string;
@ -879,6 +891,8 @@ export type MessageType =
| LoginForm | LoginForm
| RegisterForm | RegisterForm
| CommunityForm | CommunityForm
| DeleteCommunityForm
| RemoveCommunityForm
| FollowCommunityForm | FollowCommunityForm
| ListCommunitiesForm | ListCommunitiesForm
| GetFollowedCommunitiesForm | GetFollowedCommunitiesForm

View file

@ -4,6 +4,8 @@ import {
RegisterForm, RegisterForm,
UserOperation, UserOperation,
CommunityForm, CommunityForm,
DeleteCommunityForm,
RemoveCommunityForm,
PostForm, PostForm,
SavePostForm, SavePostForm,
CommentForm, CommentForm,
@ -105,18 +107,24 @@ export class WebSocketService {
this.ws.send(this.wsSendWrapper(UserOperation.Register, registerForm)); this.ws.send(this.wsSendWrapper(UserOperation.Register, registerForm));
} }
public createCommunity(communityForm: CommunityForm) { public createCommunity(form: CommunityForm) {
this.setAuth(communityForm); this.setAuth(form);
this.ws.send( this.ws.send(this.wsSendWrapper(UserOperation.CreateCommunity, form));
this.wsSendWrapper(UserOperation.CreateCommunity, communityForm)
);
} }
public editCommunity(communityForm: CommunityForm) { public editCommunity(form: CommunityForm) {
this.setAuth(communityForm); this.setAuth(form);
this.ws.send( this.ws.send(this.wsSendWrapper(UserOperation.EditCommunity, form));
this.wsSendWrapper(UserOperation.EditCommunity, communityForm) }
);
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) { public followCommunity(followCommunityForm: FollowCommunityForm) {

View file

@ -254,6 +254,7 @@
"couldnt_save_post": "Couldn't save post.", "couldnt_save_post": "Couldn't save post.",
"no_slurs": "No slurs.", "no_slurs": "No slurs.",
"not_an_admin": "Not an admin.", "not_an_admin": "Not an admin.",
"not_a_moderator": "Not a moderator.",
"site_already_exists": "Site already exists.", "site_already_exists": "Site already exists.",
"couldnt_update_site": "Couldn't update site.", "couldnt_update_site": "Couldn't update site.",
"couldnt_find_that_username_or_email": "couldnt_find_that_username_or_email":