Some more API cleanup.
- Extracted methods for is_mod_or_admin, and is_admin. - Removed admins from GetPostResponse and GetCommunityResponse. - Some cleanup.
This commit is contained in:
parent
b6a6d52a92
commit
59da2976ab
10 changed files with 50 additions and 109 deletions
2
docs/src/contributing_websocket_http_api.md
vendored
2
docs/src/contributing_websocket_http_api.md
vendored
|
@ -1054,7 +1054,6 @@ Search types are `All, Comments, Posts, Communities, Users, Url`
|
||||||
data: {
|
data: {
|
||||||
community: CommunityView,
|
community: CommunityView,
|
||||||
moderators: Vec<CommunityModeratorView>,
|
moderators: Vec<CommunityModeratorView>,
|
||||||
admins: Vec<UserView>,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -1379,7 +1378,6 @@ Only admins can remove a community.
|
||||||
comments: Vec<CommentView>,
|
comments: Vec<CommentView>,
|
||||||
community: CommunityView,
|
community: CommunityView,
|
||||||
moderators: Vec<CommunityModeratorView>,
|
moderators: Vec<CommunityModeratorView>,
|
||||||
admins: Vec<UserView>,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{claims::Claims, APIError, Oper, Perform},
|
api::{claims::Claims, is_mod_or_admin, APIError, Oper, Perform},
|
||||||
apub::{ApubLikeableType, ApubObjectType},
|
apub::{ApubLikeableType, ApubObjectType},
|
||||||
blocking,
|
blocking,
|
||||||
websocket::{
|
websocket::{
|
||||||
|
@ -13,7 +13,6 @@ use crate::{
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
comment::*,
|
comment::*,
|
||||||
comment_view::*,
|
comment_view::*,
|
||||||
community::Community,
|
|
||||||
community_view::*,
|
community_view::*,
|
||||||
moderator::*,
|
moderator::*,
|
||||||
post::*,
|
post::*,
|
||||||
|
@ -480,13 +479,7 @@ impl Perform for Oper<RemoveComment> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that only a mod or admin can remove
|
// Verify that only a mod or admin can remove
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the remove
|
// Do the remove
|
||||||
let removed = data.removed;
|
let removed = data.removed;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{claims::Claims, APIError, Oper, Perform},
|
api::{claims::Claims, is_admin, is_mod_or_admin, APIError, Oper, Perform},
|
||||||
apub::ActorType,
|
apub::ActorType,
|
||||||
blocking,
|
blocking,
|
||||||
websocket::{
|
websocket::{
|
||||||
|
@ -34,7 +34,6 @@ 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>, // TODO this should be from GetSite, shouldn't need this
|
|
||||||
pub online: usize,
|
pub online: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,13 +195,6 @@ impl Perform for Oper<GetCommunity> {
|
||||||
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
|
|
||||||
let site_creator_id = site.creator_id;
|
|
||||||
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
|
|
||||||
let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
|
|
||||||
let creator_user = admins.remove(creator_index);
|
|
||||||
admins.insert(0, creator_user);
|
|
||||||
|
|
||||||
let online = if let Some(ws) = websocket_info {
|
let online = if let Some(ws) = websocket_info {
|
||||||
if let Some(id) = ws.id {
|
if let Some(id) = ws.id {
|
||||||
ws.chatserver.do_send(JoinCommunityRoom {
|
ws.chatserver.do_send(JoinCommunityRoom {
|
||||||
|
@ -224,7 +216,6 @@ impl Perform for Oper<GetCommunity> {
|
||||||
let res = GetCommunityResponse {
|
let res = GetCommunityResponse {
|
||||||
community: community_view,
|
community: community_view,
|
||||||
moderators,
|
moderators,
|
||||||
admins,
|
|
||||||
online,
|
online,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -534,13 +525,7 @@ impl Perform for Oper<RemoveCommunity> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify its an admin (only an admin can remove a community)
|
// Verify its an admin (only an admin can remove a community)
|
||||||
let admins: Vec<i32> = blocking(pool, move |conn| {
|
is_admin(pool, user_id).await?;
|
||||||
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
|
// Do the remove
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
@ -769,13 +754,7 @@ impl Perform for Oper<BanFromCommunity> {
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
|
|
||||||
// Verify that only mods or admins can ban
|
// Verify that only mods or admins can ban
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let community_user_ban_form = CommunityUserBanForm {
|
let community_user_ban_form = CommunityUserBanForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
|
@ -858,13 +837,7 @@ impl Perform for Oper<AddModToCommunity> {
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
|
|
||||||
// Verify that only mods or admins can add mod
|
// Verify that only mods or admins can add mod
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if data.added {
|
if data.added {
|
||||||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||||
|
@ -1015,7 +988,6 @@ impl Perform for Oper<TransferCommunity> {
|
||||||
Ok(GetCommunityResponse {
|
Ok(GetCommunityResponse {
|
||||||
community: community_view,
|
community: community_view,
|
||||||
moderators,
|
moderators,
|
||||||
admins,
|
|
||||||
online: 0,
|
online: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
use crate::{websocket::WebsocketInfo, DbPool, LemmyError};
|
use crate::{blocking, websocket::WebsocketInfo, DbPool, LemmyError};
|
||||||
use actix_web::client::Client;
|
use actix_web::client::Client;
|
||||||
use lemmy_db::{community::*, community_view::*, moderator::*, site::*, user::*, user_view::*};
|
use lemmy_db::{
|
||||||
|
community::*,
|
||||||
|
community_view::*,
|
||||||
|
moderator::*,
|
||||||
|
site::*,
|
||||||
|
user::*,
|
||||||
|
user_view::*,
|
||||||
|
Crud,
|
||||||
|
};
|
||||||
|
|
||||||
pub mod claims;
|
pub mod claims;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
|
@ -44,3 +52,25 @@ pub trait Perform {
|
||||||
websocket_info: Option<WebsocketInfo>,
|
websocket_info: Option<WebsocketInfo>,
|
||||||
) -> Result<Self::Response, LemmyError>;
|
) -> Result<Self::Response, LemmyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn is_mod_or_admin(
|
||||||
|
pool: &DbPool,
|
||||||
|
user_id: i32,
|
||||||
|
community_id: i32,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let is_mod_or_admin = blocking(pool, move |conn| {
|
||||||
|
Community::is_mod_or_admin(conn, user_id, community_id)
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
if !is_mod_or_admin {
|
||||||
|
return Err(APIError::err("not_an_admin").into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> {
|
||||||
|
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
||||||
|
if !user.admin {
|
||||||
|
return Err(APIError::err("not_an_admin").into());
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{claims::Claims, APIError, Oper, Perform},
|
api::{claims::Claims, is_mod_or_admin, APIError, Oper, Perform},
|
||||||
apub::{ApubLikeableType, ApubObjectType},
|
apub::{ApubLikeableType, ApubObjectType},
|
||||||
blocking,
|
blocking,
|
||||||
fetch_iframely_and_pictrs_data,
|
fetch_iframely_and_pictrs_data,
|
||||||
|
@ -13,16 +13,13 @@ use crate::{
|
||||||
};
|
};
|
||||||
use lemmy_db::{
|
use lemmy_db::{
|
||||||
comment_view::*,
|
comment_view::*,
|
||||||
community::*,
|
|
||||||
community_view::*,
|
community_view::*,
|
||||||
moderator::*,
|
moderator::*,
|
||||||
naive_now,
|
naive_now,
|
||||||
post::*,
|
post::*,
|
||||||
post_view::*,
|
post_view::*,
|
||||||
site::*,
|
|
||||||
site_view::*,
|
site_view::*,
|
||||||
user::*,
|
user::*,
|
||||||
user_view::*,
|
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
ListingType,
|
ListingType,
|
||||||
|
@ -67,7 +64,6 @@ pub struct GetPostResponse {
|
||||||
comments: Vec<CommentView>,
|
comments: Vec<CommentView>,
|
||||||
community: CommunityView,
|
community: CommunityView,
|
||||||
moderators: Vec<CommunityModeratorView>,
|
moderators: Vec<CommunityModeratorView>,
|
||||||
admins: Vec<UserView>,
|
|
||||||
pub online: usize,
|
pub online: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,14 +330,6 @@ impl Perform for Oper<GetPost> {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let site_creator_id =
|
|
||||||
blocking(pool, move |conn| Site::read(conn, 1).map(|s| s.creator_id)).await??;
|
|
||||||
|
|
||||||
let mut admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
|
|
||||||
let creator_index = admins.iter().position(|r| r.id == site_creator_id).unwrap();
|
|
||||||
let creator_user = admins.remove(creator_index);
|
|
||||||
admins.insert(0, creator_user);
|
|
||||||
|
|
||||||
let online = if let Some(ws) = websocket_info {
|
let online = if let Some(ws) = websocket_info {
|
||||||
if let Some(id) = ws.id {
|
if let Some(id) = ws.id {
|
||||||
ws.chatserver.do_send(JoinPostRoom {
|
ws.chatserver.do_send(JoinPostRoom {
|
||||||
|
@ -366,7 +354,6 @@ impl Perform for Oper<GetPost> {
|
||||||
comments,
|
comments,
|
||||||
community,
|
community,
|
||||||
moderators,
|
moderators,
|
||||||
admins,
|
|
||||||
online,
|
online,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -770,13 +757,7 @@ impl Perform for Oper<RemovePost> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that only the mods can remove
|
// Verify that only the mods can remove
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
@ -861,13 +842,7 @@ impl Perform for Oper<LockPost> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that only the mods can lock
|
// Verify that only the mods can lock
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
@ -943,13 +918,7 @@ impl Perform for Oper<StickyPost> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that only the mods can sticky
|
// Verify that only the mods can sticky
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
is_mod_or_admin(pool, user_id, community_id).await?;
|
||||||
Community::is_mod_or_admin(conn, user_id, community_id)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
if !is_mod_or_admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let edit_id = data.edit_id;
|
let edit_id = data.edit_id;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::user::Register;
|
use super::user::Register;
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{claims::Claims, APIError, Oper, Perform},
|
api::{claims::Claims, is_admin, APIError, Oper, Perform},
|
||||||
apub::fetcher::search_by_apub_id,
|
apub::fetcher::search_by_apub_id,
|
||||||
blocking,
|
blocking,
|
||||||
version,
|
version,
|
||||||
|
@ -257,10 +257,7 @@ impl Perform for Oper<CreateSite> {
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
let user = blocking(pool, move |conn| UserView::read(conn, user_id)).await??;
|
is_admin(pool, user_id).await?;
|
||||||
if !user.admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
|
@ -311,10 +308,7 @@ impl Perform for Oper<EditSite> {
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
let user = blocking(pool, move |conn| UserView::read(conn, user_id)).await??;
|
is_admin(pool, user_id).await?;
|
||||||
if !user.admin {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let found_site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
|
let found_site = blocking(pool, move |conn| Site::read(conn, 1)).await??;
|
||||||
|
|
||||||
|
@ -693,12 +687,7 @@ impl Perform for Oper<GetSiteConfig> {
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Only let admins read this
|
// Only let admins read this
|
||||||
let admins = blocking(pool, move |conn| UserView::admins(conn)).await??;
|
is_admin(pool, user_id).await?;
|
||||||
let admin_ids: Vec<i32> = admins.into_iter().map(|m| m.id).collect();
|
|
||||||
|
|
||||||
if !admin_ids.contains(&user_id) {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let config_hjson = Settings::read_config_file()?;
|
let config_hjson = Settings::read_config_file()?;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
api::{claims::Claims, APIError, Oper, Perform},
|
api::{claims::Claims, is_admin, APIError, Oper, Perform},
|
||||||
apub::ApubObjectType,
|
apub::ApubObjectType,
|
||||||
blocking,
|
blocking,
|
||||||
websocket::{
|
websocket::{
|
||||||
|
@ -679,10 +679,7 @@ impl Perform for Oper<AddAdmin> {
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
let is_admin = move |conn: &'_ _| UserView::read(conn, user_id).map(|u| u.admin);
|
is_admin(pool, user_id).await?;
|
||||||
if !blocking(pool, is_admin).await?? {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let added = data.added;
|
let added = data.added;
|
||||||
let added_user_id = data.user_id;
|
let added_user_id = data.user_id;
|
||||||
|
@ -741,10 +738,7 @@ impl Perform for Oper<BanUser> {
|
||||||
let user_id = claims.id;
|
let user_id = claims.id;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
let is_admin = move |conn: &'_ _| UserView::read(conn, user_id).map(|u| u.admin);
|
is_admin(pool, user_id).await?;
|
||||||
if !blocking(pool, is_admin).await?? {
|
|
||||||
return Err(APIError::err("not_an_admin").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let ban = data.ban;
|
let ban = data.ban;
|
||||||
let banned_user_id = data.user_id;
|
let banned_user_id = data.user_id;
|
||||||
|
|
2
ui/src/components/community.tsx
vendored
2
ui/src/components/community.tsx
vendored
|
@ -355,7 +355,6 @@ export class Community extends Component<any, State> {
|
||||||
let data = res.data as GetCommunityResponse;
|
let data = res.data as GetCommunityResponse;
|
||||||
this.state.community = data.community;
|
this.state.community = data.community;
|
||||||
this.state.moderators = data.moderators;
|
this.state.moderators = data.moderators;
|
||||||
this.state.admins = data.admins;
|
|
||||||
this.state.online = data.online;
|
this.state.online = data.online;
|
||||||
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);
|
||||||
|
@ -442,6 +441,7 @@ export class Community extends Component<any, State> {
|
||||||
} else if (res.op == UserOperation.GetSite) {
|
} else if (res.op == UserOperation.GetSite) {
|
||||||
let data = res.data as GetSiteResponse;
|
let data = res.data as GetSiteResponse;
|
||||||
this.state.site = data.site;
|
this.state.site = data.site;
|
||||||
|
this.state.admins = data.admins;
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
ui/src/components/post.tsx
vendored
2
ui/src/components/post.tsx
vendored
|
@ -405,7 +405,6 @@ export class Post extends Component<any, PostState> {
|
||||||
this.state.comments = data.comments;
|
this.state.comments = data.comments;
|
||||||
this.state.community = data.community;
|
this.state.community = data.community;
|
||||||
this.state.moderators = data.moderators;
|
this.state.moderators = data.moderators;
|
||||||
this.state.siteRes.admins = data.admins;
|
|
||||||
this.state.online = data.online;
|
this.state.online = data.online;
|
||||||
this.state.loading = false;
|
this.state.loading = false;
|
||||||
document.title = `${this.state.post.name} - ${this.state.siteRes.site.name}`;
|
document.title = `${this.state.post.name} - ${this.state.siteRes.site.name}`;
|
||||||
|
@ -531,7 +530,6 @@ export class Post extends Component<any, PostState> {
|
||||||
let data = res.data as GetCommunityResponse;
|
let data = res.data as GetCommunityResponse;
|
||||||
this.state.community = data.community;
|
this.state.community = data.community;
|
||||||
this.state.moderators = data.moderators;
|
this.state.moderators = data.moderators;
|
||||||
this.state.siteRes.admins = data.admins;
|
|
||||||
this.setState(this.state);
|
this.setState(this.state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
ui/src/interfaces.ts
vendored
2
ui/src/interfaces.ts
vendored
|
@ -613,7 +613,6 @@ export interface GetCommunityForm {
|
||||||
export interface GetCommunityResponse {
|
export interface GetCommunityResponse {
|
||||||
community: Community;
|
community: Community;
|
||||||
moderators: Array<CommunityUser>;
|
moderators: Array<CommunityUser>;
|
||||||
admins: Array<UserView>;
|
|
||||||
online: number;
|
online: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,7 +687,6 @@ export interface GetPostResponse {
|
||||||
comments: Array<Comment>;
|
comments: Array<Comment>;
|
||||||
community: Community;
|
community: Community;
|
||||||
moderators: Array<CommunityUser>;
|
moderators: Array<CommunityUser>;
|
||||||
admins: Array<UserView>;
|
|
||||||
online: number;
|
online: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue