get_user_from_jwt_opt,
is_mod_or_admin,
Perform,
+ collect_moderated_communities,
};
use actix_web::web::Data;
use lemmy_apub::{ApubLikeableType, ApubObjectType};
use lemmy_db::{
comment::*,
+ comment_report::*,
comment_view::*,
moderator::*,
post::*,
ListingType,
Saveable,
SortType,
+ Reportable,
};
use lemmy_structs::{blocking, comment::*, send_local_notifs};
use lemmy_utils::{
ConnectionId,
LemmyError,
};
-use lemmy_websocket::{messages::SendComment, LemmyContext, UserOperation};
+use lemmy_websocket::{messages::{SendComment, SendUserRoomMessage}, LemmyContext, UserOperation};
use std::str::FromStr;
#[async_trait::async_trait(?Send)]
Ok(GetCommentsResponse { comments })
}
}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for CreateCommentReport {
+ type Response = CreateCommentReportResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ _websocket_id: Option<ConnectionId>,
+ ) -> Result<CreateCommentReportResponse, LemmyError> {
+ let data: &CreateCommentReport = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ // check size of report and check for whitespace
+ let reason = data.reason.trim();
+ if reason.is_empty() {
+ return Err(APIError::err("report_reason_required").into());
+ }
+ if reason.len() > 1000 {
+ return Err(APIError::err("report_too_long").into());
+ }
+
+ let user_id = user.id;
+ let comment_id = data.comment_id;
+ let comment = blocking(context.pool(), move |conn| {
+ CommentView::read(&conn, comment_id, None)
+ }).await??;
+
+ check_community_ban(user_id, comment.community_id, context.pool()).await?;
+
+ let report_form = CommentReportForm {
+ creator_id: user_id,
+ comment_id,
+ comment_text: comment.content,
+ reason: data.reason.to_owned(),
+ };
+
+ let _report = match blocking(context.pool(), move |conn| {
+ CommentReport::report(conn, &report_form)
+ }).await? {
+ Ok(report) => report,
+ Err(_e) => return Err(APIError::err("couldnt_create_report").into())
+ };
+
+ // to build on this, the user should get a success response, however
+ // mods should get a different response with more details
+ let res = CreateCommentReportResponse { success: true };
+
+ // TODO this needs to use a SendModRoomMessage
+ // context.chat_server().do_send(SendUserRoomMessage {
+ // op: UserOperation::CreateReport,
+ // response: res.clone(),
+ // recipient_id: user.id,
+ // websocket_id,
+ // });
+
+ Ok(res)
+ }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for ResolveCommentReport {
+ type Response = ResolveCommentReportResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ _websocket_id: Option<ConnectionId>,
+ ) -> Result<ResolveCommentReportResponse, LemmyError> {
+ let data: &ResolveCommentReport = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ let report_id = data.report_id;
+ let report = blocking(context.pool(), move |conn| {
+ CommentReportView::read(&conn, report_id)
+ }).await??;
+
+ let user_id = user.id;
+ is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
+
+ let resolved = data.resolved;
+ let resolve_fun = move |conn: &'_ _| {
+ if resolved {
+ CommentReport::resolve(conn, report_id.clone(), user_id)
+ } else {
+ CommentReport::unresolve(conn, report_id.clone())
+ }
+ };
+
+ if blocking(context.pool(),resolve_fun).await?.is_err() {
+ return Err(APIError::err("couldnt_resolve_report").into())
+ };
+
+ let report_id = data.report_id;
+ let res = ResolveCommentReportResponse {
+ report_id,
+ resolved,
+ };
+
+ // TODO this needs to use a SendModRoomMessage
+ // context.chat_server().do_send(SendUserRoomMessage {
+ // op: UserOperation::ResolveCommentReport,
+ // response: res.clone(),
+ // recipient_id: user.id,
+ // websocket_id,
+ // });
+
+ Ok(res)
+ }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for ListCommentReports {
+ type Response = ListCommentReportsResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ websocket_id: Option<ConnectionId>,
+ ) -> Result<ListCommentReportsResponse, LemmyError> {
+ let data: &ListCommentReports = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ let user_id = user.id;
+ let community_id = data.community;
+ let community_ids = collect_moderated_communities(user_id, community_id, context.pool()).await?;
+
+ let page = data.page;
+ let limit = data.limit;
+ let comments = blocking(context.pool(), move |conn| {
+ CommentReportQueryBuilder::create(conn)
+ .community_ids(community_ids)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??;
+
+ let res = ListCommentReportsResponse { comments };
+
+ context.chat_server().do_send(SendUserRoomMessage {
+ op: UserOperation::ListCommentReports,
+ response: res.clone(),
+ recipient_id: user.id,
+ websocket_id,
+ });
+
+ Ok(res)
+ }
+}
\ No newline at end of file
use crate::claims::Claims;
use actix_web::{web, web::Data};
use lemmy_db::{
- community::Community,
+ community::{Community, CommunityModerator},
community_view::CommunityUserBanView,
post::Post,
user::User_,
Crud,
DbPool,
};
-use lemmy_structs::{blocking, comment::*, community::*, post::*, report::*, site::*, user::*};
+use lemmy_structs::{blocking, comment::*, community::*, post::*, site::*, user::*};
use lemmy_utils::{settings::Settings, APIError, ConnectionId, LemmyError};
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
use serde::Deserialize;
pub mod comment;
pub mod community;
pub mod post;
-pub mod report;
pub mod site;
pub mod user;
pub mod version;
}
}
+pub(in crate) async fn collect_moderated_communities(
+ user_id: i32,
+ community_id: Option<i32>,
+ pool: &DbPool,
+) -> Result<Vec<i32>, LemmyError> {
+ if let Some(community_id) = community_id {
+ // if the user provides a community_id, just check for mod/admin privileges
+ is_mod_or_admin(pool, user_id, community_id).await?;
+ Ok(vec![community_id])
+ } else {
+ let ids = blocking(pool, move |conn: &'_ _| {
+ CommunityModerator::get_user_moderated_communities(conn, user_id)
+ }).await??;
+ Ok(ids)
+ }
+}
+
pub(in crate) fn check_optional_url(item: &Option<Option<String>>) -> Result<(), LemmyError> {
if let Some(Some(item)) = &item {
if Url::parse(item).is_err() {
UserOperation::SaveUserSettings => {
do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
}
+ UserOperation::GetReportCount => {
+ do_websocket_operation::<GetReportCount>(context, id, op, data).await
+ }
// Private Message ops
UserOperation::CreatePrivateMessage => {
do_websocket_operation::<CreatePostLike>(context, id, op, data).await
}
UserOperation::SavePost => do_websocket_operation::<SavePost>(context, id, op, data).await,
+ UserOperation::CreatePostReport => {
+ do_websocket_operation::<CreatePostReport>(context, id, op, data).await
+ }
+ UserOperation::ListPostReports => {
+ do_websocket_operation::<ListPostReports>(context, id, op, data).await
+ }
+ UserOperation::ResolvePostReport => {
+ do_websocket_operation::<ResolvePostReport>(context, id, op, data).await
+ }
// Comment ops
UserOperation::CreateComment => {
UserOperation::CreateCommentLike => {
do_websocket_operation::<CreateCommentLike>(context, id, op, data).await
}
-
- // report ops
- UserOperation::CreateReport => {
- do_websocket_operation::<CreateReport>(context, id, op, data).await
- }
- UserOperation::ListReports => {
- do_websocket_operation::<ListReports>(context, id, op, data).await
+ UserOperation::CreateCommentReport => {
+ do_websocket_operation::<CreateCommentReport>(context, id, op, data).await
}
- UserOperation::ResolveReport => {
- do_websocket_operation::<ResolveReport>(context, id, op, data).await
+ UserOperation::ListCommentReports => {
+ do_websocket_operation::<ListCommentReports>(context, id, op, data).await
}
- UserOperation::GetReportCount => {
- do_websocket_operation::<GetReportCount>(context, id, op, data).await
+ UserOperation::ResolveCommentReport => {
+ do_websocket_operation::<ResolveCommentReport>(context, id, op, data).await
}
}
}
get_user_from_jwt_opt,
is_mod_or_admin,
Perform,
+ collect_moderated_communities,
};
use actix_web::web::Data;
use lemmy_apub::{ApubLikeableType, ApubObjectType};
moderator::*,
naive_now,
post::*,
+ post_report::*,
post_view::*,
site_view::*,
Crud,
ListingType,
Saveable,
SortType,
+ Reportable,
};
use lemmy_structs::{blocking, post::*};
use lemmy_utils::{
LemmyError,
};
use lemmy_websocket::{
- messages::{GetPostUsersOnline, JoinPostRoom, SendPost},
+ messages::{GetPostUsersOnline, JoinPostRoom, SendPost, SendUserRoomMessage},
LemmyContext,
UserOperation,
};
Ok(PostJoinResponse { joined: true })
}
}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for CreatePostReport {
+ type Response = CreatePostReportResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ _websocket_id: Option<ConnectionId>,
+ ) -> Result<CreatePostReportResponse, LemmyError> {
+ let data: &CreatePostReport = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ // check size of report and check for whitespace
+ let reason = data.reason.trim();
+ if reason.is_empty() {
+ return Err(APIError::err("report_reason_required").into());
+ }
+ if reason.len() > 1000 {
+ return Err(APIError::err("report_too_long").into());
+ }
+
+ let user_id = user.id;
+ let post_id = data.post_id;
+ let post = blocking(context.pool(), move |conn| {
+ PostView::read(&conn, post_id, None)
+ }).await??;
+
+ check_community_ban(user_id, post.community_id, context.pool()).await?;
+
+ let report_form = PostReportForm {
+ creator_id: user_id,
+ post_id,
+ post_name: post.name,
+ post_url: post.url,
+ post_body: post.body,
+ reason: data.reason.to_owned(),
+ };
+
+ let _report = match blocking(context.pool(), move |conn| {
+ PostReport::report(conn, &report_form)
+ }).await? {
+ Ok(report) => report,
+ Err(_e) => return Err(APIError::err("couldnt_create_report").into())
+ };
+
+ // to build on this, the user should get a success response, however
+ // mods should get a different response with more details
+ let res = CreatePostReportResponse { success: true };
+
+ // TODO this needs to use a SendModRoomMessage
+ // context.chat_server().do_send(SendUserRoomMessage {
+ // op: UserOperation::CreateReport,
+ // response: res.clone(),
+ // recipient_id: user.id,
+ // websocket_id,
+ // });
+
+ Ok(res)
+ }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for ResolvePostReport {
+ type Response = ResolvePostReportResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ _websocket_id: Option<ConnectionId>,
+ ) -> Result<ResolvePostReportResponse, LemmyError> {
+ let data: &ResolvePostReport = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ let report_id = data.report_id;
+ let report = blocking(context.pool(), move |conn| {
+ PostReportView::read(&conn, report_id)
+ }).await??;
+
+ let user_id = user.id;
+ is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
+
+ let resolved = data.resolved;
+ let resolve_fun = move |conn: &'_ _| {
+ if resolved {
+ PostReport::resolve(conn, report_id.clone(), user_id)
+ } else {
+ PostReport::unresolve(conn, report_id.clone())
+ }
+ };
+
+ let res = ResolvePostReportResponse {
+ report_id,
+ resolved: true,
+ };
+
+ if blocking(context.pool(),resolve_fun).await?.is_err() {
+ return Err(APIError::err("couldnt_resolve_report").into())
+ };
+
+ // TODO this needs to use a SendModRoomMessage
+ // context.chat_server().do_send(SendUserRoomMessage {
+ // op: UserOperation::ResolvePostReport,
+ // response: res.clone(),
+ // recipient_id: user.id,
+ // websocket_id,
+ // });
+
+ Ok(res)
+ }
+}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for ListPostReports {
+ type Response = ListPostReportsResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ websocket_id: Option<ConnectionId>,
+ ) -> Result<ListPostReportsResponse, LemmyError> {
+ let data: &ListPostReports = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ let user_id = user.id;
+ let community_id = data.community;
+ let community_ids = collect_moderated_communities(user_id, community_id, context.pool()).await?;
+
+ let page = data.page;
+ let limit = data.limit;
+ let posts = blocking(context.pool(), move |conn| {
+ PostReportQueryBuilder::create(conn)
+ .community_ids(community_ids)
+ .page(page)
+ .limit(limit)
+ .list()
+ })
+ .await??;
+
+ let res = ListPostReportsResponse { posts };
+
+ context.chat_server().do_send(SendUserRoomMessage {
+ op: UserOperation::ListPostReports,
+ response: res.clone(),
+ recipient_id: user.id,
+ websocket_id,
+ });
+
+ Ok(res)
+ }
+}
+++ /dev/null
-use actix_web::web::Data;
-use std::str::FromStr;
-
-use lemmy_db::{comment_report::*, comment_view::*, post_report::*, post_view::*, Reportable, ReportType,};
-use lemmy_structs::{blocking, report::*};
-use lemmy_utils::{APIError, ConnectionId, LemmyError};
-use lemmy_websocket::{LemmyContext, UserOperation, messages::SendUserRoomMessage};
-
-use crate::{check_community_ban, get_user_from_jwt, is_mod_or_admin, Perform};
-
-const MAX_REPORT_LEN: usize = 1000;
-
-#[async_trait::async_trait(?Send)]
-impl Perform for CreateReport {
- type Response = CreateReportResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<CreateReportResponse, LemmyError> {
- let data: &CreateReport = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
-
- // check size of report and check for whitespace
- let reason = data.reason.clone();
- if reason.trim().is_empty() {
- return Err(APIError::err("report_reason_required").into());
- }
- if reason.len() > MAX_REPORT_LEN {
- return Err(APIError::err("report_too_long").into());
- }
-
- let report_type = ReportType::from_str(&data.report_type)?;
- let user_id = user.id;
- match report_type {
- ReportType::Comment => { create_comment_report(context, data, user_id).await?; }
- ReportType::Post => { create_post_report(context, data, user_id).await?; }
- }
-
- // to build on this, the user should get a success response, however
- // mods should get a different response with more details
- let res = CreateReportResponse { success: true };
-
- context.chat_server().do_send(SendUserRoomMessage {
- op: UserOperation::CreateReport,
- response: res.clone(),
- recipient_id: user.id,
- websocket_id,
- });
-
- Ok(res)
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for GetReportCount {
- type Response = GetReportCountResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<GetReportCountResponse, LemmyError> {
- let data: &GetReportCount = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
- let community_id = data.community;
-
- // Check for mod/admin privileges
- is_mod_or_admin(context.pool(), user.id, community_id).await?;
-
- let comment_reports = blocking(context.pool(), move |conn| {
- CommentReportQueryBuilder::create(conn)
- .community_id(community_id)
- .resolved(false)
- .count()
- })
- .await??;
- let post_reports = blocking(context.pool(), move |conn| {
- PostReportQueryBuilder::create(conn)
- .community_id(community_id)
- .resolved(false)
- .count()
- })
- .await??;
-
- let res = GetReportCountResponse {
- community: community_id,
- comment_reports,
- post_reports,
- };
-
- context.chat_server().do_send(SendUserRoomMessage {
- op: UserOperation::ListReports,
- response: res.clone(),
- recipient_id: user.id,
- websocket_id,
- });
-
- Ok(res)
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for ListReports {
- type Response = ListReportsResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<ListReportsResponse, LemmyError> {
- let data: &ListReports = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
- let community_id = data.community;
-
- // Check for mod/admin privileges
- is_mod_or_admin(context.pool(), user.id, community_id).await?;
-
- let page = data.page;
- let limit = data.limit;
- let comments = blocking(context.pool(), move |conn| {
- CommentReportQueryBuilder::create(conn)
- .community_id(community_id)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
-
- let posts = blocking(context.pool(), move |conn| {
- PostReportQueryBuilder::create(conn)
- .community_id(community_id)
- .page(page)
- .limit(limit)
- .list()
- })
- .await??;
-
- let res = ListReportsResponse { comments, posts };
-
- context.chat_server().do_send(SendUserRoomMessage {
- op: UserOperation::ListReports,
- response: res.clone(),
- recipient_id: user.id,
- websocket_id,
- });
-
- Ok(res)
- }
-}
-
-#[async_trait::async_trait(?Send)]
-impl Perform for ResolveReport {
- type Response = ResolveReportResponse;
-
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- websocket_id: Option<ConnectionId>,
- ) -> Result<ResolveReportResponse, LemmyError> {
- let data: &ResolveReport = &self;
- let user = get_user_from_jwt(&data.auth, context.pool()).await?;
-
- let report_type = ReportType::from_str(&data.report_type)?;
- let user_id = user.id;
- match report_type {
- ReportType::Comment => { resolve_comment_report(context, data, user_id).await?; }
- ReportType::Post => { resolve_post_report(context, data, user_id).await?; }
- }
-
- let report_id = data.report_id;
- let res = ResolveReportResponse {
- report_type: data.report_type.to_owned(),
- report_id,
- resolved: true,
- };
-
- context.chat_server().do_send(SendUserRoomMessage {
- op: UserOperation::ResolveReport,
- response: res.clone(),
- recipient_id: user.id,
- websocket_id,
- });
-
- Ok(res)
- }
-}
-
-async fn create_comment_report(
- context: &Data<LemmyContext>,
- data: &CreateReport,
- user_id: i32,
-) -> Result<(), LemmyError> {
- let comment_id = data.entity_id;
- let comment = blocking(context.pool(), move |conn| {
- CommentView::read(&conn, comment_id, None)
- }).await??;
-
- check_community_ban(user_id, comment.community_id, context.pool()).await?;
-
- let report_form = CommentReportForm {
- creator_id: user_id,
- comment_id,
- comment_text: comment.content,
- reason: data.reason.to_owned(),
- };
-
- return match blocking(context.pool(), move |conn| {
- CommentReport::report(conn, &report_form)
- }).await? {
- Ok(_) => Ok(()),
- Err(_e) => Err(APIError::err("couldnt_create_report").into())
- };
-}
-
-async fn create_post_report(
- context: &Data<LemmyContext>,
- data: &CreateReport,
- user_id: i32,
-) -> Result<(), LemmyError> {
- let post_id = data.entity_id;
- let post = blocking(context.pool(), move |conn| {
- PostView::read(&conn, post_id, None)
- }).await??;
-
- check_community_ban(user_id, post.community_id, context.pool()).await?;
-
- let report_form = PostReportForm {
- creator_id: user_id,
- post_id,
- post_name: post.name,
- post_url: post.url,
- post_body: post.body,
- reason: data.reason.to_owned(),
- };
-
- return match blocking(context.pool(), move |conn| {
- PostReport::report(conn, &report_form)
- }).await? {
- Ok(_) => Ok(()),
- Err(_e) => Err(APIError::err("couldnt_create_report").into())
- };
-}
-
-async fn resolve_comment_report(
- context: &Data<LemmyContext>,
- data: &ResolveReport,
- user_id: i32,
-) -> Result<(), LemmyError> {
- let report_id = data.report_id;
- let report = blocking(context.pool(), move |conn| {
- CommentReportView::read(&conn, report_id)
- }).await??;
-
- is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
-
- let resolved = data.resolved;
- let resolve_fun = move |conn: &'_ _| {
- if resolved {
- CommentReport::resolve(conn, report_id.clone(), user_id)
- } else {
- CommentReport::unresolve(conn, report_id.clone())
- }
- };
-
- if blocking(context.pool(),resolve_fun).await?.is_err() {
- return Err(APIError::err("couldnt_resolve_report").into())
- };
-
- Ok(())
-}
-
-async fn resolve_post_report(
- context: &Data<LemmyContext>,
- data: &ResolveReport,
- user_id: i32,
-) -> Result<(), LemmyError> {
- let report_id = data.report_id;
- let report = blocking(context.pool(), move |conn| {
- PostReportView::read(&conn, report_id)
- }).await??;
-
- is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
-
- let resolved = data.resolved;
- let resolve_fun = move |conn: &'_ _| {
- if resolved {
- PostReport::resolve(conn, report_id.clone(), user_id)
- } else {
- PostReport::unresolve(conn, report_id.clone())
- }
- };
-
- if blocking(context.pool(),resolve_fun).await?.is_err() {
- return Err(APIError::err("couldnt_resolve_report").into())
- };
-
- Ok(())
-}
get_user_from_jwt_opt,
is_admin,
Perform,
+ collect_moderated_communities
};
use actix_web::web::Data;
use anyhow::Context;
use lemmy_apub::ApubObjectType;
use lemmy_db::{
comment::*,
+ comment_report::CommentReportView,
comment_view::*,
community::*,
community_view::*,
naive_now,
password_reset_request::*,
post::*,
+ post_report::PostReportView,
post_view::*,
private_message::*,
private_message_view::*,
Ok(UserJoinResponse { joined: true })
}
}
+
+#[async_trait::async_trait(?Send)]
+impl Perform for GetReportCount {
+ type Response = GetReportCountResponse;
+
+ async fn perform(
+ &self,
+ context: &Data<LemmyContext>,
+ websocket_id: Option<ConnectionId>,
+ ) -> Result<GetReportCountResponse, LemmyError> {
+ let data: &GetReportCount = &self;
+ let user = get_user_from_jwt(&data.auth, context.pool()).await?;
+
+ let user_id = user.id;
+ let community_id = data.community;
+ let community_ids = collect_moderated_communities(user_id, community_id, context.pool()).await?;
+
+ let res = {
+ if community_ids.is_empty() {
+ GetReportCountResponse {
+ community: None,
+ comment_reports: 0,
+ post_reports: 0,
+ }
+ } else {
+ let ids = community_ids.clone();
+ let comment_reports = blocking(context.pool(), move |conn|
+ CommentReportView::get_report_count(conn, &ids)).await??;
+
+ let ids = community_ids.clone();
+ let post_reports = blocking(context.pool(), move |conn|
+ PostReportView::get_report_count(conn, &ids)).await??;
+
+ GetReportCountResponse {
+ community: data.community,
+ comment_reports,
+ post_reports,
+ }
+ }
+ };
+
+ context.chat_server().do_send(SendUserRoomMessage {
+ op: UserOperation::GetReportCount,
+ response: res.clone(),
+ recipient_id: user.id,
+ websocket_id,
+ });
+
+ Ok(res)
+ }
+}
fn report(conn: &PgConnection, comment_report_form: &CommentReportForm) -> Result<Self, Error> {
use crate::schema::comment_report::dsl::*;
insert_into(comment_report)
- .values(comment_report_form)
- .get_result::<Self>(conn)
+ .values(comment_report_form)
+ .get_result::<Self>(conn)
}
fn resolve(conn: &PgConnection, report_id: i32, by_user_id: i32) -> Result<usize, Error> {
use crate::schema::comment_report::dsl::*;
update(comment_report.find(report_id))
- .set((
- resolved.eq(true),
- resolver_id.eq(by_user_id),
- updated.eq(naive_now()),
- ))
- .execute(conn)
+ .set((
+ resolved.eq(true),
+ resolver_id.eq(by_user_id),
+ updated.eq(naive_now()),
+ ))
+ .execute(conn)
}
fn unresolve(conn: &PgConnection, report_id: i32) -> Result<usize, Error> {
use crate::schema::comment_report::dsl::*;
update(comment_report.find(report_id))
- .set((
- resolved.eq(false),
- updated.eq(naive_now()),
- ))
- .execute(conn)
+ .set((
+ resolved.eq(false),
+ updated.eq(naive_now()),
+ ))
+ .execute(conn)
}
}
#[derive(
- Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, Clone,
+Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, Clone,
)]
#[table_name = "comment_report_view"]
pub struct CommentReportView {
pub struct CommentReportQueryBuilder<'a> {
conn: &'a PgConnection,
query: comment_report_view::BoxedQuery<'a, Pg>,
- for_community_id: Option<i32>,
+ for_community_ids: Option<Vec<i32>>,
page: Option<i64>,
limit: Option<i64>,
resolved: Option<bool>,
.find(report_id)
.first::<Self>(conn)
}
+
+ pub fn get_report_count(conn: &PgConnection, community_ids: &Vec<i32>) -> Result<i32, Error> {
+ use super::comment_report::comment_report_view::dsl::*;
+ comment_report_view
+ .filter(resolved.eq(false).and(community_id.eq_any(community_ids)))
+ .select(sql::<sql_types::Integer>("COUNT(*)"))
+ .first::<i32>(conn)
+ }
}
impl<'a> CommentReportQueryBuilder<'a> {
CommentReportQueryBuilder {
conn,
query,
- for_community_id: None,
+ for_community_ids: None,
page: None,
limit: None,
resolved: Some(false),
}
}
- pub fn community_id<T: MaybeOptional<i32>>(mut self, community_id: T) -> Self {
- self.for_community_id = community_id.get_optional();
+ pub fn community_ids<T: MaybeOptional<Vec<i32>>>(mut self, community_ids: T) -> Self {
+ self.for_community_ids = community_ids.get_optional();
self
}
let mut query = self.query;
- if let Some(comm_id) = self.for_community_id {
- query = query.filter(community_id.eq(comm_id));
+ if let Some(comm_ids) = self.for_community_ids {
+ query = query.filter(community_id.eq_any(comm_ids));
}
if let Some(resolved_flag) = self.resolved {
.offset(offset)
.load::<CommentReportView>(self.conn)
}
-
- pub fn count(self) -> Result<usize, Error> {
- use super::comment_report::comment_report_view::dsl::*;
- let mut query = self.query;
-
- if let Some(comm_id) = self.for_community_id {
- query = query.filter(community_id.eq(comm_id));
- }
-
- if let Some(resolved_flag) = self.resolved {
- query = query.filter(resolved.eq(resolved_flag));
- }
-
- query.execute(self.conn)
- }
}
-
-
use crate::schema::community_moderator::dsl::*;
diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
}
+
+ pub fn get_user_moderated_communities(conn: &PgConnection, for_user_id: i32) -> Result<Vec<i32>, Error> {
+ use crate::schema::community_moderator::dsl::*;
+ community_moderator
+ .filter(user_id.eq(for_user_id))
+ .select(community_id)
+ .load::<i32>(conn)
+ }
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
Url,
}
-#[derive(EnumString, ToString, Debug, Serialize, Deserialize)]
-pub enum ReportType {
- Comment,
- Post,
-}
-
pub fn fuzzy_search(q: &str) -> String {
let replaced = q.replace(" ", "%");
format!("%{}%", replaced)
#[belongs_to(Post)]
#[table_name = "post_report"]
pub struct PostReport {
- pub id: i32,
- pub creator_id: i32,
- pub post_id: i32,
- pub post_name: String,
- pub post_url: Option<String>,
- pub post_body: Option<String>,
- pub reason: String,
- pub resolved: bool,
- pub resolver_id: Option<i32>,
- pub published: chrono::NaiveDateTime,
- pub updated: Option<chrono::NaiveDateTime>,
+ pub id: i32,
+ pub creator_id: i32,
+ pub post_id: i32,
+ pub post_name: String,
+ pub post_url: Option<String>,
+ pub post_body: Option<String>,
+ pub reason: String,
+ pub resolved: bool,
+ pub resolver_id: Option<i32>,
+ pub published: chrono::NaiveDateTime,
+ pub updated: Option<chrono::NaiveDateTime>,
}
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "post_report"]
pub struct PostReportForm {
- pub creator_id: i32,
- pub post_id: i32,
- pub post_name: String,
- pub post_url: Option<String>,
- pub post_body: Option<String>,
- pub reason: String,
+ pub creator_id: i32,
+ pub post_id: i32,
+ pub post_name: String,
+ pub post_url: Option<String>,
+ pub post_body: Option<String>,
+ pub reason: String,
}
impl Reportable<PostReportForm> for PostReport {
- fn report(conn: &PgConnection, post_report_form: &PostReportForm) -> Result<Self, Error> {
- use crate::schema::post_report::dsl::*;
- insert_into(post_report)
- .values(post_report_form)
- .get_result::<Self>(conn)
- }
-
- fn resolve(conn: &PgConnection, report_id: i32, by_user_id: i32) -> Result<usize, Error> {
- use crate::schema::post_report::dsl::*;
- update(post_report.find(report_id))
- .set((
- resolved.eq(true),
- resolver_id.eq(by_user_id),
- updated.eq(naive_now()),
- ))
- .execute(conn)
- }
-
- fn unresolve(conn: &PgConnection, report_id: i32) -> Result<usize, Error> {
- use crate::schema::post_report::dsl::*;
- update(post_report.find(report_id))
- .set((
- resolved.eq(false),
- updated.eq(naive_now()),
- ))
- .execute(conn)
- }
+ fn report(conn: &PgConnection, post_report_form: &PostReportForm) -> Result<Self, Error> {
+ use crate::schema::post_report::dsl::*;
+ insert_into(post_report)
+ .values(post_report_form)
+ .get_result::<Self>(conn)
+ }
+
+ fn resolve(conn: &PgConnection, report_id: i32, by_user_id: i32) -> Result<usize, Error> {
+ use crate::schema::post_report::dsl::*;
+ update(post_report.find(report_id))
+ .set((
+ resolved.eq(true),
+ resolver_id.eq(by_user_id),
+ updated.eq(naive_now()),
+ ))
+ .execute(conn)
+ }
+
+ fn unresolve(conn: &PgConnection, report_id: i32) -> Result<usize, Error> {
+ use crate::schema::post_report::dsl::*;
+ update(post_report.find(report_id))
+ .set((
+ resolved.eq(false),
+ updated.eq(naive_now()),
+ ))
+ .execute(conn)
+ }
}
#[derive(
)]
#[table_name = "post_report_view"]
pub struct PostReportView {
- pub id: i32,
- pub creator_id: i32,
- pub post_id: i32,
- pub post_name: String,
- pub post_url: Option<String>,
- pub post_body: Option<String>,
- pub reason: String,
- pub resolved: bool,
- pub resolver_id: Option<i32>,
- pub published: chrono::NaiveDateTime,
- pub updated: Option<chrono::NaiveDateTime>,
- pub community_id: i32,
- pub creator_name: String,
- pub post_creator_id: i32,
- pub post_creator_name: String,
+ pub id: i32,
+ pub creator_id: i32,
+ pub post_id: i32,
+ pub post_name: String,
+ pub post_url: Option<String>,
+ pub post_body: Option<String>,
+ pub reason: String,
+ pub resolved: bool,
+ pub resolver_id: Option<i32>,
+ pub published: chrono::NaiveDateTime,
+ pub updated: Option<chrono::NaiveDateTime>,
+ pub community_id: i32,
+ pub creator_name: String,
+ pub post_creator_id: i32,
+ pub post_creator_name: String,
}
impl PostReportView {
- pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
- use super::post_report::post_report_view::dsl::*;
- post_report_view
- .find(report_id)
- .first::<Self>(conn)
- }
+ pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
+ use super::post_report::post_report_view::dsl::*;
+ post_report_view
+ .find(report_id)
+ .first::<Self>(conn)
+ }
+
+ pub fn get_report_count(conn: &PgConnection, community_ids: &Vec<i32>) -> Result<i32, Error> {
+ use super::post_report::post_report_view::dsl::*;
+ post_report_view
+ .filter(resolved.eq(false).and(community_id.eq_any(community_ids)))
+ .select(sql::<sql_types::Integer>("COUNT(*)"))
+ .first::<i32>(conn)
+ }
}
pub struct PostReportQueryBuilder<'a> {
- conn: &'a PgConnection,
- query: post_report_view::BoxedQuery<'a, Pg>,
- for_community_id: Option<i32>,
- page: Option<i64>,
- limit: Option<i64>,
- resolved: Option<bool>,
+ conn: &'a PgConnection,
+ query: post_report_view::BoxedQuery<'a, Pg>,
+ for_community_ids: Option<Vec<i32>>,
+ page: Option<i64>,
+ limit: Option<i64>,
+ resolved: Option<bool>,
}
impl<'a> PostReportQueryBuilder<'a> {
- pub fn create(conn: &'a PgConnection) -> Self {
- use super::post_report::post_report_view::dsl::*;
-
- let query = post_report_view.into_boxed();
-
- PostReportQueryBuilder {
- conn,
- query,
- for_community_id: None,
- page: None,
- limit: None,
- resolved: Some(false),
- }
- }
-
- pub fn community_id<T: MaybeOptional<i32>>(mut self, community_id: T) -> Self {
- self.for_community_id = community_id.get_optional();
- self
+ pub fn create(conn: &'a PgConnection) -> Self {
+ use super::post_report::post_report_view::dsl::*;
+
+ let query = post_report_view.into_boxed();
+
+ PostReportQueryBuilder {
+ conn,
+ query,
+ for_community_ids: None,
+ page: None,
+ limit: None,
+ resolved: Some(false),
}
+ }
- pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
- self.page = page.get_optional();
- self
- }
-
- pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
- self.limit = limit.get_optional();
- self
- }
-
- pub fn resolved<T: MaybeOptional<bool>>(mut self, resolved: T) -> Self {
- self.resolved = resolved.get_optional();
- self
- }
+ pub fn community_ids<T: MaybeOptional<Vec<i32>>>(mut self, community_ids: T) -> Self {
+ self.for_community_ids = community_ids.get_optional();
+ self
+ }
- pub fn list(self) -> Result<Vec<PostReportView>, Error> {
- use super::post_report::post_report_view::dsl::*;
+ pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
+ self.page = page.get_optional();
+ self
+ }
- let mut query = self.query;
+ pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
+ self.limit = limit.get_optional();
+ self
+ }
- if let Some(comm_id) = self.for_community_id {
- query = query.filter(community_id.eq(comm_id));
- }
+ pub fn resolved<T: MaybeOptional<bool>>(mut self, resolved: T) -> Self {
+ self.resolved = resolved.get_optional();
+ self
+ }
- if let Some(resolved_flag) = self.resolved {
- query = query.filter(resolved.eq(resolved_flag));
- }
+ pub fn list(self) -> Result<Vec<PostReportView>, Error> {
+ use super::post_report::post_report_view::dsl::*;
- let (limit, offset) = limit_and_offset(self.page, self.limit);
+ let mut query = self.query;
- query
- .order_by(published.asc())
- .limit(limit)
- .offset(offset)
- .load::<PostReportView>(self.conn)
+ if let Some(comm_ids) = self.for_community_ids {
+ query = query.filter(community_id.eq_any(comm_ids));
}
- pub fn count(self) -> Result<usize, Error> {
- use super::post_report::post_report_view::dsl::*;
- let mut query = self.query;
-
- if let Some(comm_id) = self.for_community_id {
- query = query.filter(community_id.eq(comm_id));
- }
+ if let Some(resolved_flag) = self.resolved {
+ query = query.filter(resolved.eq(resolved_flag));
+ }
- if let Some(resolved_flag) = self.resolved {
- query = query.filter(resolved.eq(resolved_flag));
- }
+ let (limit, offset) = limit_and_offset(self.page, self.limit);
- query.execute(self.conn)
- }
+ query
+ .order_by(published.asc())
+ .limit(limit)
+ .offset(offset)
+ .load::<PostReportView>(self.conn)
+ }
}
joinable!(user_mention -> user_ (recipient_id));
allow_tables_to_appear_in_same_query!(
- activity,
- category,
- comment,
- comment_aggregates_fast,
- comment_like,
- comment_report,
- comment_saved,
- community,
- community_aggregates_fast,
- community_follower,
- community_moderator,
- community_user_ban,
- mod_add,
- mod_add_community,
- mod_ban,
- mod_ban_from_community,
- mod_lock_post,
- mod_remove_comment,
- mod_remove_community,
- mod_remove_post,
- mod_sticky_post,
- password_reset_request,
- post,
- post_aggregates_fast,
- post_like,
- post_read,
- post_report,
- post_saved,
- private_message,
- site,
- user_,
- user_ban,
- user_fast,
- user_mention,
+ activity,
+ category,
+ comment,
+ comment_aggregates_fast,
+ comment_like,
+ comment_report,
+ comment_saved,
+ community,
+ community_aggregates_fast,
+ community_follower,
+ community_moderator,
+ community_user_ban,
+ mod_add,
+ mod_add_community,
+ mod_ban,
+ mod_ban_from_community,
+ mod_lock_post,
+ mod_remove_comment,
+ mod_remove_community,
+ mod_remove_post,
+ mod_sticky_post,
+ password_reset_request,
+ post,
+ post_aggregates_fast,
+ post_like,
+ post_read,
+ post_report,
+ post_saved,
+ private_message,
+ site,
+ user_,
+ user_ban,
+ user_fast,
+ user_mention,
);
diesel = "1.4"
actix-web = { version = "3.0" }
chrono = { version = "0.4", features = ["serde"] }
-serde_json = { version = "1.0", features = ["preserve_order"]}
\ No newline at end of file
+serde_json = { version = "1.0", features = ["preserve_order"]}
-use lemmy_db::comment_view::CommentView;
+use lemmy_db::{
+ comment_view::CommentView,
+ comment_report::CommentReportView,
+};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
pub struct GetCommentsResponse {
pub comments: Vec<CommentView>,
}
+
+#[derive(Serialize, Deserialize)]
+pub struct CreateCommentReport {
+ pub comment_id: i32,
+ pub reason: String,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct CreateCommentReportResponse {
+ pub success: bool,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct ResolveCommentReport {
+ pub report_id: i32,
+ pub resolved: bool,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct ResolveCommentReportResponse {
+ pub report_id: i32,
+ pub resolved: bool,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct ListCommentReports {
+ pub page: Option<i64>,
+ pub limit: Option<i64>,
+ pub community: Option<i32>,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct ListCommentReportsResponse {
+ pub comments: Vec<CommentReportView>,
+}
pub mod comment;
pub mod community;
pub mod post;
-pub mod report;
pub mod site;
pub mod user;
pub mod websocket;
use lemmy_db::{
comment_view::CommentView,
community_view::{CommunityModeratorView, CommunityView},
+ post_report::PostReportView,
post_view::PostView,
};
use serde::{Deserialize, Serialize};
pub struct PostJoinResponse {
pub joined: bool,
}
+
+#[derive(Serialize, Deserialize)]
+pub struct CreatePostReport {
+ pub post_id: i32,
+ pub reason: String,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct CreatePostReportResponse {
+ pub success: bool,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct ResolvePostReport {
+ pub report_id: i32,
+ pub resolved: bool,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct ResolvePostReportResponse {
+ pub report_id: i32,
+ pub resolved: bool,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct ListPostReports {
+ pub page: Option<i64>,
+ pub limit: Option<i64>,
+ pub community: Option<i32>,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct ListPostReportsResponse {
+ pub posts: Vec<PostReportView>,
+}
+++ /dev/null
-use lemmy_db::{comment_report::CommentReportView, post_report::PostReportView};
-use serde::{Deserialize, Serialize};
-
-#[derive(Serialize, Deserialize)]
-pub struct CreateReport {
- pub report_type: String,
- pub entity_id: i32,
- pub reason: String,
- pub auth: String,
-}
-
-#[derive(Serialize, Deserialize, Clone)]
-pub struct CreateReportResponse {
- pub success: bool,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct ListReports {
- pub page: Option<i64>,
- pub limit: Option<i64>,
- pub community: i32,
- pub auth: String,
-}
-
-#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct ListReportsResponse {
- pub posts: Vec<PostReportView>,
- pub comments: Vec<CommentReportView>,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct GetReportCount {
- pub community: i32,
- pub auth: String,
-}
-
-#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct GetReportCountResponse {
- pub community: i32,
- pub comment_reports: usize,
- pub post_reports: usize,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct ResolveReport {
- pub report_type: String,
- pub report_id: i32,
- pub resolved: bool,
- pub auth: String,
-}
-
-#[derive(Serialize, Deserialize, Clone, Debug)]
-pub struct ResolveReportResponse {
- pub report_type: String,
- pub report_id: i32,
- pub resolved: bool,
-}
pub struct UserJoinResponse {
pub joined: bool,
}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct GetReportCount {
+ pub community: Option<i32>,
+ pub auth: String,
+}
+
+#[derive(Serialize, Deserialize, Clone, Debug)]
+pub struct GetReportCountResponse {
+ pub community: Option<i32>,
+ pub comment_reports: i32,
+ pub post_reports: i32,
+}
MarkCommentAsRead,
SaveComment,
CreateCommentLike,
+ CreateCommentReport,
+ ResolveCommentReport,
+ ListCommentReports,
GetPosts,
CreatePostLike,
EditPost,
LockPost,
StickyPost,
SavePost,
- CreateReport,
- ResolveReport,
- ListReports,
+ CreatePostReport,
+ ResolvePostReport,
+ ListPostReports,
GetReportCount,
EditCommunity,
DeleteCommunity,
use actix_web::{error::ErrorBadRequest, *};
use lemmy_api::Perform;
use lemmy_rate_limit::RateLimit;
-use lemmy_structs::{comment::*, community::*, post::*, report::*, site::*, user::*};
+use lemmy_structs::{comment::*, community::*, post::*, site::*, user::*};
use lemmy_websocket::LemmyContext;
use serde::Deserialize;
.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>))
- .route("/join", web::post().to(route_post::<CommunityJoin>))
+ .route("/join", web::post().to(route_post::<CommunityJoin>)),
)
// Post
.service(
.route("/like", web::post().to(route_post::<CreatePostLike>))
.route("/save", web::put().to(route_post::<SavePost>))
.route("/join", web::post().to(route_post::<PostJoin>))
+ .route("/report", web::post().to(route_post::<CreatePostReport>))
+ .route("/report/resolve", web::put().to(route_post::<ResolvePostReport>))
+ .route("/report/list", web::get().to(route_get::<ListPostReports>))
)
// Comment
.service(
- web::scope("/comment")
+ web::scope("/comment")
.wrap(rate_limit.message())
.route("", web::post().to(route_post::<CreateComment>))
.route("", web::put().to(route_post::<EditComment>))
.route("/like", web::post().to(route_post::<CreateCommentLike>))
.route("/save", web::put().to(route_post::<SaveComment>))
.route("/list", web::get().to(route_get::<GetComments>))
+ .route("/report", web::post().to(route_post::<CreateCommentReport>))
+ .route("/report/resolve", web::put().to(route_post::<ResolveCommentReport>))
+ .route("/report/list", web::get().to(route_get::<ListCommentReports>))
)
// Private Message
.service(
.route(
"/save_user_settings",
web::put().to(route_post::<SaveUserSettings>),
+ )
+ .route(
+ "/report_count",
+ web::get().to(route_get::<GetReportCount>)
),
)
// Admin Actions
web::resource("/admin/add")
.wrap(rate_limit.message())
.route(web::post().to(route_post::<AddAdmin>)),
- )
- // Reports
- .service(
- web::scope("/report")
- .wrap(rate_limit.message())
- .route("", web::get().to(route_get::<GetReportCount>))
- .route("",web::post().to(route_post::<CreateReport>))
- .route("/resolve",web::put().to(route_post::<ResolveReport>))
- .route("/list", web::get().to(route_get::<ListReports>))
),
);
}