mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-21 22:27:08 +00:00
Implement reports for private messages (#2433)
* Implement reports for private messages * finish private message report view + test * implement api for pm reports * merge list report api calls into one, move report count to site * fix compile error * Revert "merge list report api calls into one, move report count to site" This reverts commit 3bf3b06a705c6bcf2bf20d07e2819b81298790f3. * add websocket messages for pm report created/resolved * remove private_message_report_view * add joinable private_message_report -> person_alias_1 * Address review comments
This commit is contained in:
parent
09246a20fb
commit
004efd5d94
|
@ -1,4 +1,4 @@
|
|||
use crate::Perform;
|
||||
use crate::{check_report_reason, Perform};
|
||||
use activitypub_federation::core::object_id::ObjectId;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
|
@ -29,14 +29,8 @@ impl Perform for CreateCommentReport {
|
|||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||
|
||||
// check size of report and check for whitespace
|
||||
let reason = data.reason.trim();
|
||||
if reason.is_empty() {
|
||||
return Err(LemmyError::from_message("report_reason_required"));
|
||||
}
|
||||
if reason.chars().count() > 1000 {
|
||||
return Err(LemmyError::from_message("report_too_long"));
|
||||
}
|
||||
let reason = self.reason.trim();
|
||||
check_report_reason(reason, context)?;
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
let comment_id = data.comment_id;
|
||||
|
@ -51,7 +45,7 @@ impl Perform for CreateCommentReport {
|
|||
creator_id: person_id,
|
||||
comment_id,
|
||||
original_comment_text: comment_view.comment.content,
|
||||
reason: data.reason.to_owned(),
|
||||
reason: reason.to_owned(),
|
||||
};
|
||||
|
||||
let report = blocking(context.pool(), move |conn| {
|
||||
|
|
|
@ -1,7 +1,15 @@
|
|||
use actix_web::{web, web::Data};
|
||||
use captcha::Captcha;
|
||||
use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_api_common::{
|
||||
comment::*,
|
||||
community::*,
|
||||
person::*,
|
||||
post::*,
|
||||
private_message::*,
|
||||
site::*,
|
||||
websocket::*,
|
||||
};
|
||||
use lemmy_utils::{error::LemmyError, utils::check_slurs, ConnectionId};
|
||||
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
|
||||
use serde::Deserialize;
|
||||
|
||||
|
@ -12,6 +20,7 @@ mod local_user;
|
|||
mod post;
|
||||
mod post_report;
|
||||
mod private_message;
|
||||
mod private_message_report;
|
||||
mod site;
|
||||
mod websocket;
|
||||
|
||||
|
@ -98,6 +107,15 @@ pub async fn match_websocket_operation(
|
|||
UserOperation::MarkPrivateMessageAsRead => {
|
||||
do_websocket_operation::<MarkPrivateMessageAsRead>(context, id, op, data).await
|
||||
}
|
||||
UserOperation::CreatePrivateMessageReport => {
|
||||
do_websocket_operation::<CreatePrivateMessageReport>(context, id, op, data).await
|
||||
}
|
||||
UserOperation::ResolvePrivateMessageReport => {
|
||||
do_websocket_operation::<ResolvePrivateMessageReport>(context, id, op, data).await
|
||||
}
|
||||
UserOperation::ListPrivateMessageReports => {
|
||||
do_websocket_operation::<ListPrivateMessageReports>(context, id, op, data).await
|
||||
}
|
||||
|
||||
// Site ops
|
||||
UserOperation::GetModlog => do_websocket_operation::<GetModlog>(context, id, op, data).await,
|
||||
|
@ -208,6 +226,18 @@ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
|
|||
base64::encode(concat_letters)
|
||||
}
|
||||
|
||||
/// Check size of report and remove whitespace
|
||||
pub(crate) fn check_report_reason(reason: &str, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||
check_slurs(reason, &context.settings().slur_regex())?;
|
||||
if reason.is_empty() {
|
||||
return Err(LemmyError::from_message("report_reason_required"));
|
||||
}
|
||||
if reason.chars().count() > 1000 {
|
||||
return Err(LemmyError::from_message("report_too_long"));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use lemmy_api_common::utils::check_validator_time;
|
||||
|
|
|
@ -4,7 +4,7 @@ use lemmy_api_common::{
|
|||
person::{GetReportCount, GetReportCountResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentReportView, PostReportView};
|
||||
use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView};
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
|
@ -36,10 +36,22 @@ impl Perform for GetReportCount {
|
|||
})
|
||||
.await??;
|
||||
|
||||
let private_message_reports = if admin && community_id.is_none() {
|
||||
Some(
|
||||
blocking(context.pool(), move |conn| {
|
||||
PrivateMessageReportView::get_report_count(conn)
|
||||
})
|
||||
.await??,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let res = GetReportCountResponse {
|
||||
community_id,
|
||||
comment_reports,
|
||||
post_reports,
|
||||
private_message_reports,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::Perform;
|
||||
use crate::{check_report_reason, Perform};
|
||||
use activitypub_federation::core::object_id::ObjectId;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
|
@ -29,14 +29,8 @@ impl Perform for CreatePostReport {
|
|||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
|
||||
|
||||
// check size of report and check for whitespace
|
||||
let reason = data.reason.trim();
|
||||
if reason.is_empty() {
|
||||
return Err(LemmyError::from_message("report_reason_required"));
|
||||
}
|
||||
if reason.chars().count() > 1000 {
|
||||
return Err(LemmyError::from_message("report_too_long"));
|
||||
}
|
||||
let reason = self.reason.trim();
|
||||
check_report_reason(reason, context)?;
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_id = data.post_id;
|
||||
|
@ -53,7 +47,7 @@ impl Perform for CreatePostReport {
|
|||
original_post_name: post_view.post.name,
|
||||
original_post_url: post_view.post.url,
|
||||
original_post_body: post_view.post.body,
|
||||
reason: data.reason.to_owned(),
|
||||
reason: reason.to_owned(),
|
||||
};
|
||||
|
||||
let report = blocking(context.pool(), move |conn| {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::Perform;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
person::{MarkPrivateMessageAsRead, PrivateMessageResponse},
|
||||
private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_db_schema::{source::private_message::PrivateMessage, traits::Crud};
|
||||
|
|
75
crates/api/src/private_message_report/create.rs
Normal file
75
crates/api/src/private_message_report/create.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use crate::{check_report_reason, Perform};
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::{
|
||||
private_message::PrivateMessage,
|
||||
private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
|
||||
},
|
||||
traits::{Crud, Reportable},
|
||||
};
|
||||
use lemmy_db_views::structs::PrivateMessageReportView;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for CreatePrivateMessageReport {
|
||||
type Response = PrivateMessageReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
) -> Result<Self::Response, LemmyError> {
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&self.auth, context.pool(), context.secret()).await?;
|
||||
|
||||
let reason = self.reason.trim();
|
||||
check_report_reason(reason, context)?;
|
||||
|
||||
let person_id = local_user_view.person.id;
|
||||
let private_message_id = self.private_message_id;
|
||||
let private_message = blocking(context.pool(), move |conn| {
|
||||
PrivateMessage::read(conn, private_message_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let report_form = PrivateMessageReportForm {
|
||||
creator_id: person_id,
|
||||
private_message_id,
|
||||
original_pm_text: private_message.content,
|
||||
reason: reason.to_owned(),
|
||||
};
|
||||
|
||||
let report = blocking(context.pool(), move |conn| {
|
||||
PrivateMessageReport::report(conn, &report_form)
|
||||
})
|
||||
.await?
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_create_report"))?;
|
||||
|
||||
let private_message_report_view = blocking(context.pool(), move |conn| {
|
||||
PrivateMessageReportView::read(conn, report.id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let res = PrivateMessageReportResponse {
|
||||
private_message_report_view,
|
||||
};
|
||||
|
||||
context.chat_server().do_send(SendModRoomMessage {
|
||||
op: UserOperation::CreatePrivateMessageReport,
|
||||
response: res.clone(),
|
||||
community_id: CommunityId(0),
|
||||
websocket_id,
|
||||
});
|
||||
|
||||
// TODO: consider federating this
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
46
crates/api/src/private_message_report/list.rs
Normal file
46
crates/api/src/private_message_report/list.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::Perform;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt, is_admin},
|
||||
};
|
||||
use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_websocket::LemmyContext;
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for ListPrivateMessageReports {
|
||||
type Response = ListPrivateMessageReportsResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, _websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
_websocket_id: Option<ConnectionId>,
|
||||
) -> Result<Self::Response, LemmyError> {
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&self.auth, context.pool(), context.secret()).await?;
|
||||
|
||||
is_admin(&local_user_view)?;
|
||||
|
||||
let unresolved_only = self.unresolved_only;
|
||||
let page = self.page;
|
||||
let limit = self.limit;
|
||||
let private_message_reports = blocking(context.pool(), move |conn| {
|
||||
PrivateMessageReportQuery::builder()
|
||||
.conn(conn)
|
||||
.unresolved_only(unresolved_only)
|
||||
.page(page)
|
||||
.limit(limit)
|
||||
.build()
|
||||
.list()
|
||||
})
|
||||
.await??;
|
||||
|
||||
let res = ListPrivateMessageReportsResponse {
|
||||
private_message_reports,
|
||||
};
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
3
crates/api/src/private_message_report/mod.rs
Normal file
3
crates/api/src/private_message_report/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod create;
|
||||
mod list;
|
||||
mod resolve;
|
64
crates/api/src/private_message_report/resolve.rs
Normal file
64
crates/api/src/private_message_report/resolve.rs
Normal file
|
@ -0,0 +1,64 @@
|
|||
use crate::Perform;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport},
|
||||
utils::{blocking, get_local_user_view_from_jwt, is_admin},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::CommunityId,
|
||||
source::private_message_report::PrivateMessageReport,
|
||||
traits::Reportable,
|
||||
};
|
||||
use lemmy_db_views::structs::PrivateMessageReportView;
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_websocket::{messages::SendModRoomMessage, LemmyContext, UserOperation};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl Perform for ResolvePrivateMessageReport {
|
||||
type Response = PrivateMessageReportResponse;
|
||||
|
||||
#[tracing::instrument(skip(context, websocket_id))]
|
||||
async fn perform(
|
||||
&self,
|
||||
context: &Data<LemmyContext>,
|
||||
websocket_id: Option<ConnectionId>,
|
||||
) -> Result<Self::Response, LemmyError> {
|
||||
let local_user_view =
|
||||
get_local_user_view_from_jwt(&self.auth, context.pool(), context.secret()).await?;
|
||||
|
||||
is_admin(&local_user_view)?;
|
||||
|
||||
let resolved = self.resolved;
|
||||
let report_id = self.report_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let resolve_fn = move |conn: &'_ _| {
|
||||
if resolved {
|
||||
PrivateMessageReport::resolve(conn, report_id, person_id)
|
||||
} else {
|
||||
PrivateMessageReport::unresolve(conn, report_id, person_id)
|
||||
}
|
||||
};
|
||||
|
||||
blocking(context.pool(), resolve_fn)
|
||||
.await?
|
||||
.map_err(|e| LemmyError::from_error_message(e, "couldnt_resolve_report"))?;
|
||||
|
||||
let private_message_report_view = blocking(context.pool(), move |conn| {
|
||||
PrivateMessageReportView::read(conn, report_id)
|
||||
})
|
||||
.await??;
|
||||
|
||||
let res = PrivateMessageReportResponse {
|
||||
private_message_report_view,
|
||||
};
|
||||
|
||||
context.chat_server().do_send(SendModRoomMessage {
|
||||
op: UserOperation::ResolvePrivateMessageReport,
|
||||
response: res.clone(),
|
||||
community_id: CommunityId(0),
|
||||
websocket_id,
|
||||
});
|
||||
|
||||
Ok(res)
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ pub mod comment;
|
|||
pub mod community;
|
||||
pub mod person;
|
||||
pub mod post;
|
||||
pub mod private_message;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod request;
|
||||
pub mod sensitive;
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
use crate::sensitive::Sensitive;
|
||||
use lemmy_db_views::structs::{CommentView, PostView, PrivateMessageView};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
||||
CommentSortType,
|
||||
SortType,
|
||||
};
|
||||
use lemmy_db_views::structs::{CommentView, PostView};
|
||||
use lemmy_db_views_actor::structs::{
|
||||
CommentReplyView,
|
||||
CommunityModeratorView,
|
||||
|
@ -13,18 +18,6 @@ pub struct Login {
|
|||
pub username_or_email: Sensitive<String>,
|
||||
pub password: Sensitive<String>,
|
||||
}
|
||||
use lemmy_db_schema::{
|
||||
newtypes::{
|
||||
CommentReplyId,
|
||||
CommunityId,
|
||||
LanguageId,
|
||||
PersonId,
|
||||
PersonMentionId,
|
||||
PrivateMessageId,
|
||||
},
|
||||
CommentSortType,
|
||||
SortType,
|
||||
};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct Register {
|
||||
|
@ -249,52 +242,6 @@ pub struct PasswordChangeAfterReset {
|
|||
pub password_verify: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct CreatePrivateMessage {
|
||||
pub content: String,
|
||||
pub recipient_id: PersonId,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct EditPrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub content: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct DeletePrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub deleted: bool,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct MarkPrivateMessageAsRead {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub read: bool,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct GetPrivateMessages {
|
||||
pub unread_only: Option<bool>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessagesResponse {
|
||||
pub private_messages: Vec<PrivateMessageView>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessageResponse {
|
||||
pub private_message_view: PrivateMessageView,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct GetReportCount {
|
||||
pub community_id: Option<CommunityId>,
|
||||
|
@ -306,6 +253,7 @@ pub struct GetReportCountResponse {
|
|||
pub community_id: Option<CommunityId>,
|
||||
pub comment_reports: i64,
|
||||
pub post_reports: i64,
|
||||
pub private_message_reports: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
|
|
83
crates/api_common/src/private_message.rs
Normal file
83
crates/api_common/src/private_message.rs
Normal file
|
@ -0,0 +1,83 @@
|
|||
use crate::sensitive::Sensitive;
|
||||
use lemmy_db_schema::newtypes::{PersonId, PrivateMessageId, PrivateMessageReportId};
|
||||
use lemmy_db_views::structs::{PrivateMessageReportView, PrivateMessageView};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct CreatePrivateMessage {
|
||||
pub content: String,
|
||||
pub recipient_id: PersonId,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct EditPrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub content: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct DeletePrivateMessage {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub deleted: bool,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct MarkPrivateMessageAsRead {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub read: bool,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct GetPrivateMessages {
|
||||
pub unread_only: Option<bool>,
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessagesResponse {
|
||||
pub private_messages: Vec<PrivateMessageView>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessageResponse {
|
||||
pub private_message_view: PrivateMessageView,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct CreatePrivateMessageReport {
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub reason: String,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessageReportResponse {
|
||||
pub private_message_report_view: PrivateMessageReportView,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct ResolvePrivateMessageReport {
|
||||
pub report_id: PrivateMessageReportId,
|
||||
pub resolved: bool,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||
pub struct ListPrivateMessageReports {
|
||||
pub page: Option<i64>,
|
||||
pub limit: Option<i64>,
|
||||
/// Only shows the unresolved reports
|
||||
pub unresolved_only: Option<bool>,
|
||||
pub auth: Sensitive<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct ListPrivateMessageReportsResponse {
|
||||
pub private_message_reports: Vec<PrivateMessageReportView>,
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
use actix_web::{web, web::Data};
|
||||
use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*};
|
||||
use lemmy_api_common::{comment::*, community::*, person::*, post::*, private_message::*, site::*};
|
||||
use lemmy_utils::{error::LemmyError, ConnectionId};
|
||||
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperationCrud};
|
||||
use serde::Deserialize;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::PerformCrud;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
person::{CreatePrivateMessage, PrivateMessageResponse},
|
||||
private_message::{CreatePrivateMessage, PrivateMessageResponse},
|
||||
utils::{
|
||||
blocking,
|
||||
check_person_block,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::PerformCrud;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
person::{DeletePrivateMessage, PrivateMessageResponse},
|
||||
private_message::{DeletePrivateMessage, PrivateMessageResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_apub::activities::deletion::send_apub_delete_private_message;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::PerformCrud;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
person::{GetPrivateMessages, PrivateMessagesResponse},
|
||||
private_message::{GetPrivateMessages, PrivateMessagesResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_db_schema::traits::DeleteableOrRemoveable;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::PerformCrud;
|
||||
use actix_web::web::Data;
|
||||
use lemmy_api_common::{
|
||||
person::{EditPrivateMessage, PrivateMessageResponse},
|
||||
private_message::{EditPrivateMessage, PrivateMessageResponse},
|
||||
utils::{blocking, get_local_user_view_from_jwt},
|
||||
};
|
||||
use lemmy_apub::protocol::activities::{
|
||||
|
|
|
@ -16,6 +16,7 @@ pub mod person_mention;
|
|||
pub mod post;
|
||||
pub mod post_report;
|
||||
pub mod private_message;
|
||||
pub mod private_message_report;
|
||||
pub mod registration_application;
|
||||
pub mod secret;
|
||||
pub mod site;
|
||||
|
|
62
crates/db_schema/src/impls/private_message_report.rs
Normal file
62
crates/db_schema/src/impls/private_message_report.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
use crate::{
|
||||
newtypes::{PersonId, PrivateMessageReportId},
|
||||
source::private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
|
||||
traits::Reportable,
|
||||
utils::naive_now,
|
||||
};
|
||||
use diesel::{dsl::*, result::Error, *};
|
||||
|
||||
impl Reportable for PrivateMessageReport {
|
||||
type Form = PrivateMessageReportForm;
|
||||
type IdType = PrivateMessageReportId;
|
||||
/// creates a comment report and returns it
|
||||
///
|
||||
/// * `conn` - the postgres connection
|
||||
/// * `comment_report_form` - the filled CommentReportForm to insert
|
||||
fn report(conn: &PgConnection, pm_report_form: &PrivateMessageReportForm) -> Result<Self, Error> {
|
||||
use crate::schema::private_message_report::dsl::*;
|
||||
insert_into(private_message_report)
|
||||
.values(pm_report_form)
|
||||
.get_result::<Self>(conn)
|
||||
}
|
||||
|
||||
/// resolve a pm report
|
||||
///
|
||||
/// * `conn` - the postgres connection
|
||||
/// * `report_id` - the id of the report to resolve
|
||||
/// * `by_resolver_id` - the id of the user resolving the report
|
||||
fn resolve(
|
||||
conn: &PgConnection,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
use crate::schema::private_message_report::dsl::*;
|
||||
update(private_message_report.find(report_id))
|
||||
.set((
|
||||
resolved.eq(true),
|
||||
resolver_id.eq(by_resolver_id),
|
||||
updated.eq(naive_now()),
|
||||
))
|
||||
.execute(conn)
|
||||
}
|
||||
|
||||
/// unresolve a comment report
|
||||
///
|
||||
/// * `conn` - the postgres connection
|
||||
/// * `report_id` - the id of the report to unresolve
|
||||
/// * `by_resolver_id` - the id of the user unresolving the report
|
||||
fn unresolve(
|
||||
conn: &PgConnection,
|
||||
report_id: Self::IdType,
|
||||
by_resolver_id: PersonId,
|
||||
) -> Result<usize, Error> {
|
||||
use crate::schema::private_message_report::dsl::*;
|
||||
update(private_message_report.find(report_id))
|
||||
.set((
|
||||
resolved.eq(false),
|
||||
resolver_id.eq(by_resolver_id),
|
||||
updated.eq(naive_now()),
|
||||
))
|
||||
.execute(conn)
|
||||
}
|
||||
}
|
|
@ -69,6 +69,10 @@ pub struct CommentReportId(i32);
|
|||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct PostReportId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct PrivateMessageReportId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType))]
|
||||
pub struct LanguageId(pub i32);
|
||||
|
|
|
@ -454,6 +454,20 @@ table! {
|
|||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
private_message_report (id) {
|
||||
id -> Int4,
|
||||
creator_id -> Int4,
|
||||
private_message_id -> Int4,
|
||||
original_pm_text -> Text,
|
||||
reason -> Text,
|
||||
resolved -> Bool,
|
||||
resolver_id -> Nullable<Int4>,
|
||||
published -> Timestamp,
|
||||
updated -> Nullable<Timestamp>,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
site (id) {
|
||||
id -> Int4,
|
||||
|
@ -667,9 +681,11 @@ joinable!(person_mention -> person_alias_1 (recipient_id));
|
|||
joinable!(comment_reply -> person_alias_1 (recipient_id));
|
||||
joinable!(post -> person_alias_1 (creator_id));
|
||||
joinable!(comment -> person_alias_1 (creator_id));
|
||||
joinable!(private_message_report -> person_alias_1 (resolver_id));
|
||||
|
||||
joinable!(post_report -> person_alias_2 (resolver_id));
|
||||
joinable!(comment_report -> person_alias_2 (resolver_id));
|
||||
joinable!(private_message_report -> person_alias_2 (resolver_id));
|
||||
|
||||
joinable!(person_block -> person (person_id));
|
||||
joinable!(person_block -> person_alias_1 (target_id));
|
||||
|
@ -733,6 +749,7 @@ joinable!(post -> language (language_id));
|
|||
joinable!(comment -> language (language_id));
|
||||
joinable!(local_user_language -> language (language_id));
|
||||
joinable!(local_user_language -> local_user (local_user_id));
|
||||
joinable!(private_message_report -> private_message (private_message_id));
|
||||
|
||||
joinable!(admin_purge_comment -> person (admin_person_id));
|
||||
joinable!(admin_purge_comment -> post (post_id));
|
||||
|
@ -780,6 +797,7 @@ allow_tables_to_appear_in_same_query!(
|
|||
post_report,
|
||||
post_saved,
|
||||
private_message,
|
||||
private_message_report,
|
||||
site,
|
||||
site_aggregates,
|
||||
person_alias_1,
|
||||
|
|
|
@ -17,6 +17,7 @@ pub mod person_mention;
|
|||
pub mod post;
|
||||
pub mod post_report;
|
||||
pub mod private_message;
|
||||
pub mod private_message_report;
|
||||
pub mod registration_application;
|
||||
pub mod secret;
|
||||
pub mod site;
|
||||
|
|
34
crates/db_schema/src/source/private_message_report.rs
Normal file
34
crates/db_schema/src/source/private_message_report.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
use crate::newtypes::{PersonId, PrivateMessageId, PrivateMessageReportId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "full")]
|
||||
use crate::schema::private_message_report;
|
||||
|
||||
#[derive(PartialEq, Serialize, Deserialize, Debug, Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Queryable, Associations, Identifiable))]
|
||||
#[cfg_attr(
|
||||
feature = "full",
|
||||
belongs_to(crate::source::private_message::PrivateMessage)
|
||||
)]
|
||||
#[cfg_attr(feature = "full", table_name = "private_message_report")]
|
||||
pub struct PrivateMessageReport {
|
||||
pub id: PrivateMessageReportId,
|
||||
pub creator_id: PersonId,
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub original_pm_text: String,
|
||||
pub reason: String,
|
||||
pub resolved: bool,
|
||||
pub resolver_id: Option<PersonId>,
|
||||
pub published: chrono::NaiveDateTime,
|
||||
pub updated: Option<chrono::NaiveDateTime>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
|
||||
#[cfg_attr(feature = "full", table_name = "private_message_report")]
|
||||
pub struct PrivateMessageReportForm {
|
||||
pub creator_id: PersonId,
|
||||
pub private_message_id: PrivateMessageId,
|
||||
pub original_pm_text: String,
|
||||
pub reason: String,
|
||||
}
|
|
@ -14,6 +14,9 @@ pub mod post_report_view;
|
|||
#[cfg(feature = "full")]
|
||||
pub mod post_view;
|
||||
#[cfg(feature = "full")]
|
||||
#[cfg(feature = "full")]
|
||||
pub mod private_message_report_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod private_message_view;
|
||||
#[cfg(feature = "full")]
|
||||
pub mod registration_application_view;
|
||||
|
|
223
crates/db_views/src/private_message_report_view.rs
Normal file
223
crates/db_views/src/private_message_report_view.rs
Normal file
|
@ -0,0 +1,223 @@
|
|||
use crate::structs::PrivateMessageReportView;
|
||||
use diesel::{result::Error, *};
|
||||
use lemmy_db_schema::{
|
||||
newtypes::PrivateMessageReportId,
|
||||
schema::{person, person_alias_1, person_alias_2, private_message, private_message_report},
|
||||
source::{
|
||||
person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
|
||||
private_message::PrivateMessage,
|
||||
private_message_report::PrivateMessageReport,
|
||||
},
|
||||
traits::{ToSafe, ViewToVec},
|
||||
utils::limit_and_offset,
|
||||
};
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
type PrivateMessageReportViewTuple = (
|
||||
PrivateMessageReport,
|
||||
PrivateMessage,
|
||||
PersonSafe,
|
||||
PersonSafeAlias1,
|
||||
Option<PersonSafeAlias2>,
|
||||
);
|
||||
|
||||
impl PrivateMessageReportView {
|
||||
/// returns the PrivateMessageReportView for the provided report_id
|
||||
///
|
||||
/// * `report_id` - the report id to obtain
|
||||
pub fn read(conn: &PgConnection, report_id: PrivateMessageReportId) -> Result<Self, Error> {
|
||||
let (private_message_report, private_message, private_message_creator, creator, resolver) =
|
||||
private_message_report::table
|
||||
.find(report_id)
|
||||
.inner_join(private_message::table)
|
||||
.inner_join(person::table.on(private_message::creator_id.eq(person::id)))
|
||||
.inner_join(
|
||||
person_alias_1::table.on(private_message_report::creator_id.eq(person_alias_1::id)),
|
||||
)
|
||||
.left_join(
|
||||
person_alias_2::table
|
||||
.on(private_message_report::resolver_id.eq(person_alias_2::id.nullable())),
|
||||
)
|
||||
.select((
|
||||
private_message_report::all_columns,
|
||||
private_message::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
PersonAlias1::safe_columns_tuple(),
|
||||
PersonAlias2::safe_columns_tuple().nullable(),
|
||||
))
|
||||
.first::<PrivateMessageReportViewTuple>(conn)?;
|
||||
|
||||
Ok(Self {
|
||||
private_message_report,
|
||||
private_message,
|
||||
private_message_creator,
|
||||
creator,
|
||||
resolver,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the current unresolved post report count for the communities you mod
|
||||
pub fn get_report_count(conn: &PgConnection) -> Result<i64, Error> {
|
||||
use diesel::dsl::*;
|
||||
|
||||
private_message_report::table
|
||||
.inner_join(private_message::table)
|
||||
.filter(private_message_report::resolved.eq(false))
|
||||
.into_boxed()
|
||||
.select(count(private_message_report::id))
|
||||
.first::<i64>(conn)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(TypedBuilder)]
|
||||
#[builder(field_defaults(default))]
|
||||
pub struct PrivateMessageReportQuery<'a> {
|
||||
#[builder(!default)]
|
||||
conn: &'a PgConnection,
|
||||
page: Option<i64>,
|
||||
limit: Option<i64>,
|
||||
unresolved_only: Option<bool>,
|
||||
}
|
||||
|
||||
impl<'a> PrivateMessageReportQuery<'a> {
|
||||
pub fn list(self) -> Result<Vec<PrivateMessageReportView>, Error> {
|
||||
let mut query = private_message_report::table
|
||||
.inner_join(private_message::table)
|
||||
.inner_join(person::table.on(private_message::creator_id.eq(person::id)))
|
||||
.inner_join(
|
||||
person_alias_1::table.on(private_message_report::creator_id.eq(person_alias_1::id)),
|
||||
)
|
||||
.left_join(
|
||||
person_alias_2::table
|
||||
.on(private_message_report::resolver_id.eq(person_alias_2::id.nullable())),
|
||||
)
|
||||
.select((
|
||||
private_message_report::all_columns,
|
||||
private_message::all_columns,
|
||||
Person::safe_columns_tuple(),
|
||||
PersonAlias1::safe_columns_tuple(),
|
||||
PersonAlias2::safe_columns_tuple().nullable(),
|
||||
))
|
||||
.into_boxed();
|
||||
|
||||
if self.unresolved_only.unwrap_or(true) {
|
||||
query = query.filter(private_message_report::resolved.eq(false));
|
||||
}
|
||||
|
||||
let (limit, offset) = limit_and_offset(self.page, self.limit)?;
|
||||
|
||||
query = query
|
||||
.order_by(private_message::published.desc())
|
||||
.limit(limit)
|
||||
.offset(offset);
|
||||
|
||||
let res = query.load::<PrivateMessageReportViewTuple>(self.conn)?;
|
||||
|
||||
Ok(PrivateMessageReportView::from_tuple_to_vec(res))
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewToVec for PrivateMessageReportView {
|
||||
type DbTuple = PrivateMessageReportViewTuple;
|
||||
fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
|
||||
items
|
||||
.into_iter()
|
||||
.map(|a| Self {
|
||||
private_message_report: a.0,
|
||||
private_message: a.1,
|
||||
private_message_creator: a.2,
|
||||
creator: a.3,
|
||||
resolver: a.4,
|
||||
})
|
||||
.collect::<Vec<Self>>()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::private_message_report_view::PrivateMessageReportQuery;
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
person::{Person, PersonForm},
|
||||
private_message::{PrivateMessage, PrivateMessageForm},
|
||||
private_message_report::{PrivateMessageReport, PrivateMessageReportForm},
|
||||
},
|
||||
traits::{Crud, Reportable},
|
||||
utils::establish_unpooled_connection,
|
||||
};
|
||||
use serial_test::serial;
|
||||
|
||||
#[test]
|
||||
#[serial]
|
||||
fn test_crud() {
|
||||
let conn = establish_unpooled_connection();
|
||||
|
||||
let new_person_1 = PersonForm {
|
||||
name: "timmy_mrv".into(),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
let inserted_timmy = Person::create(&conn, &new_person_1).unwrap();
|
||||
|
||||
let new_person_2 = PersonForm {
|
||||
name: "jessica_mrv".into(),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
let inserted_jessica = Person::create(&conn, &new_person_2).unwrap();
|
||||
|
||||
// timmy sends private message to jessica
|
||||
let pm_form = PrivateMessageForm {
|
||||
creator_id: inserted_timmy.id,
|
||||
recipient_id: inserted_jessica.id,
|
||||
content: "something offensive".to_string(),
|
||||
..Default::default()
|
||||
};
|
||||
let pm = PrivateMessage::create(&conn, &pm_form).unwrap();
|
||||
|
||||
// jessica reports private message
|
||||
let pm_report_form = PrivateMessageReportForm {
|
||||
creator_id: inserted_jessica.id,
|
||||
original_pm_text: pm.content.clone(),
|
||||
private_message_id: pm.id,
|
||||
reason: "its offensive".to_string(),
|
||||
};
|
||||
let pm_report = PrivateMessageReport::report(&conn, &pm_report_form).unwrap();
|
||||
|
||||
let reports = PrivateMessageReportQuery::builder()
|
||||
.conn(&conn)
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
assert_eq!(1, reports.len());
|
||||
assert!(!reports[0].private_message_report.resolved);
|
||||
assert_eq!(inserted_timmy.name, reports[0].private_message_creator.name);
|
||||
assert_eq!(inserted_jessica.name, reports[0].creator.name);
|
||||
assert_eq!(pm_report.reason, reports[0].private_message_report.reason);
|
||||
assert_eq!(pm.content, reports[0].private_message.content);
|
||||
|
||||
let new_person_3 = PersonForm {
|
||||
name: "admin_mrv".into(),
|
||||
public_key: Some("pubkey".to_string()),
|
||||
..PersonForm::default()
|
||||
};
|
||||
let inserted_admin = Person::create(&conn, &new_person_3).unwrap();
|
||||
|
||||
// admin resolves the report (after taking appropriate action)
|
||||
PrivateMessageReport::resolve(&conn, pm_report.id, inserted_admin.id).unwrap();
|
||||
|
||||
let reports = PrivateMessageReportQuery::builder()
|
||||
.conn(&conn)
|
||||
.unresolved_only(Some(false))
|
||||
.build()
|
||||
.list()
|
||||
.unwrap();
|
||||
assert_eq!(1, reports.len());
|
||||
assert!(reports[0].private_message_report.resolved);
|
||||
assert!(reports[0].resolver.is_some());
|
||||
assert_eq!(
|
||||
inserted_admin.name,
|
||||
reports[0].resolver.as_ref().unwrap().name
|
||||
);
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ use lemmy_db_schema::{
|
|||
post::Post,
|
||||
post_report::PostReport,
|
||||
private_message::PrivateMessage,
|
||||
private_message_report::PrivateMessageReport,
|
||||
registration_application::RegistrationApplication,
|
||||
site::Site,
|
||||
},
|
||||
|
@ -94,6 +95,15 @@ pub struct PrivateMessageView {
|
|||
pub recipient: PersonSafeAlias1,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct PrivateMessageReportView {
|
||||
pub private_message_report: PrivateMessageReport,
|
||||
pub private_message: PrivateMessage,
|
||||
pub private_message_creator: PersonSafe,
|
||||
pub creator: PersonSafeAlias1,
|
||||
pub resolver: Option<PersonSafeAlias2>,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
pub struct RegistrationApplicationView {
|
||||
pub registration_application: RegistrationApplication,
|
||||
|
|
|
@ -134,6 +134,9 @@ pub enum UserOperation {
|
|||
PasswordReset,
|
||||
PasswordChange,
|
||||
MarkPrivateMessageAsRead,
|
||||
CreatePrivateMessageReport,
|
||||
ResolvePrivateMessageReport,
|
||||
ListPrivateMessageReports,
|
||||
UserJoin,
|
||||
PostJoin,
|
||||
CommunityJoin,
|
||||
|
|
|
@ -55,6 +55,7 @@ pub struct SendUserRoomMessage<OP: ToString, Response> {
|
|||
pub websocket_id: Option<ConnectionId>,
|
||||
}
|
||||
|
||||
/// Send message to all users viewing the given community.
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct SendCommunityRoomMessage<OP: ToString, Response> {
|
||||
|
@ -64,6 +65,7 @@ pub struct SendCommunityRoomMessage<OP: ToString, Response> {
|
|||
pub websocket_id: Option<ConnectionId>,
|
||||
}
|
||||
|
||||
/// Send message to mods of a given community. Set community_id = 0 to send to site admins.
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "()")]
|
||||
pub struct SendModRoomMessage<Response> {
|
||||
|
|
|
@ -6,8 +6,8 @@ use crate::{
|
|||
use lemmy_api_common::{
|
||||
comment::CommentResponse,
|
||||
community::CommunityResponse,
|
||||
person::PrivateMessageResponse,
|
||||
post::PostResponse,
|
||||
private_message::PrivateMessageResponse,
|
||||
utils::{blocking, check_person_block, get_interface_language, send_email_to_user},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
|
1
migrations/2022-09-07-114618_pm-reports/down.sql
Normal file
1
migrations/2022-09-07-114618_pm-reports/down.sql
Normal file
|
@ -0,0 +1 @@
|
|||
drop table private_message_report;
|
12
migrations/2022-09-07-114618_pm-reports/up.sql
Normal file
12
migrations/2022-09-07-114618_pm-reports/up.sql
Normal file
|
@ -0,0 +1,12 @@
|
|||
create table private_message_report (
|
||||
id serial primary key,
|
||||
creator_id int references person on update cascade on delete cascade not null, -- user reporting comment
|
||||
private_message_id int references private_message on update cascade on delete cascade not null, -- comment being reported
|
||||
original_pm_text text not null,
|
||||
reason text not null,
|
||||
resolved bool not null default false,
|
||||
resolver_id int references person on update cascade on delete cascade, -- user resolving report
|
||||
published timestamp not null default now(),
|
||||
updated timestamp null,
|
||||
unique(private_message_id, creator_id) -- users should only be able to report a pm once
|
||||
);
|
|
@ -1,6 +1,14 @@
|
|||
use actix_web::*;
|
||||
use lemmy_api::Perform;
|
||||
use lemmy_api_common::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
|
||||
use lemmy_api_common::{
|
||||
comment::*,
|
||||
community::*,
|
||||
person::*,
|
||||
post::*,
|
||||
private_message::*,
|
||||
site::*,
|
||||
websocket::*,
|
||||
};
|
||||
use lemmy_api_crud::PerformCrud;
|
||||
use lemmy_utils::rate_limit::RateLimit;
|
||||
use lemmy_websocket::{routes::chat_route, LemmyContext};
|
||||
|
@ -148,6 +156,18 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
|
|||
.route(
|
||||
"/mark_as_read",
|
||||
web::post().to(route_post::<MarkPrivateMessageAsRead>),
|
||||
)
|
||||
.route(
|
||||
"/report",
|
||||
web::post().to(route_post::<CreatePrivateMessageReport>),
|
||||
)
|
||||
.route(
|
||||
"/report/resolve",
|
||||
web::put().to(route_post::<ResolvePrivateMessageReport>),
|
||||
)
|
||||
.route(
|
||||
"/report/list",
|
||||
web::get().to(route_get::<ListPrivateMessageReports>),
|
||||
),
|
||||
)
|
||||
// User
|
||||
|
|
Loading…
Reference in a new issue