Adding report views.

This commit is contained in:
Dessalines 2020-12-16 22:03:03 -05:00
parent 1cf520254d
commit 05c3e471ae
16 changed files with 684 additions and 505 deletions

View File

@ -10,9 +10,15 @@ use crate::{
use actix_web::web::Data;
use lemmy_apub::{ApubLikeableType, ApubObjectType};
use lemmy_db::{
comment_report::*,
source::{comment::*, moderator::*, post::*, user::*},
source::{
comment::*,
comment_report::{CommentReport, CommentReportForm},
moderator::*,
post::*,
user::*,
},
views::{
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
comment_view::{CommentQueryBuilder, CommentView},
site_view::SiteView,
},
@ -776,7 +782,7 @@ impl Perform for ResolveCommentReport {
.await??;
let user_id = user.id;
is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
is_mod_or_admin(context.pool(), user_id, report.community.id).await?;
let resolved = data.resolved;
let resolve_fun = move |conn: &'_ _| {
@ -800,7 +806,7 @@ impl Perform for ResolveCommentReport {
context.chat_server().do_send(SendModRoomMessage {
op: UserOperation::ResolveCommentReport,
response: res.clone(),
community_id: report.community_id,
community_id: report.community.id,
websocket_id,
});

View File

@ -11,11 +11,15 @@ use actix_web::web::Data;
use lemmy_apub::{ApubLikeableType, ApubObjectType};
use lemmy_db::{
naive_now,
post_report::*,
source::{moderator::*, post::*},
source::{
moderator::*,
post::*,
post_report::{PostReport, PostReportForm},
},
views::{
comment_view::CommentQueryBuilder,
community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
post_report_view::{PostReportQueryBuilder, PostReportView},
post_view::{PostQueryBuilder, PostView},
site_view::SiteView,
},
@ -835,7 +839,7 @@ impl Perform for ResolvePostReport {
.await??;
let user_id = user.id;
is_mod_or_admin(context.pool(), user_id, report.community_id).await?;
is_mod_or_admin(context.pool(), user_id, report.community.id).await?;
let resolved = data.resolved;
let resolve_fun = move |conn: &'_ _| {
@ -858,7 +862,7 @@ impl Perform for ResolvePostReport {
context.chat_server().do_send(SendModRoomMessage {
op: UserOperation::ResolvePostReport,
response: res.clone(),
community_id: report.community_id,
community_id: report.community.id,
websocket_id,
});

View File

@ -15,10 +15,8 @@ use captcha::{gen, Difficulty};
use chrono::Duration;
use lemmy_apub::ApubObjectType;
use lemmy_db::{
comment_report::CommentReportView,
diesel_option_overwrite,
naive_now,
post_report::PostReportView,
source::{
comment::*,
community::*,
@ -31,11 +29,13 @@ use lemmy_db::{
user_mention::*,
},
views::{
comment_report_view::CommentReportView,
comment_view::CommentQueryBuilder,
community::{
community_follower_view::CommunityFollowerView,
community_moderator_view::CommunityModeratorView,
},
post_report_view::PostReportView,
post_view::PostQueryBuilder,
private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView},
site_view::SiteView,

View File

@ -1,235 +0,0 @@
use diesel::{dsl::*, pg::Pg, result::Error, *};
use serde::{Deserialize, Serialize};
use crate::{
limit_and_offset,
naive_now,
schema::comment_report,
source::comment::Comment,
MaybeOptional,
Reportable,
};
table! {
comment_report_view (id) {
id -> Int4,
creator_id -> Int4,
comment_id -> Int4,
original_comment_text -> Text,
reason -> Text,
resolved -> Bool,
resolver_id -> Nullable<Int4>,
published -> Timestamp,
updated -> Nullable<Timestamp>,
post_id -> Int4,
current_comment_text -> Text,
community_id -> Int4,
creator_actor_id -> Text,
creator_name -> Varchar,
creator_preferred_username -> Nullable<Varchar>,
creator_avatar -> Nullable<Text>,
creator_local -> Bool,
comment_creator_id -> Int4,
comment_creator_actor_id -> Text,
comment_creator_name -> Varchar,
comment_creator_preferred_username -> Nullable<Varchar>,
comment_creator_avatar -> Nullable<Text>,
comment_creator_local -> Bool,
resolver_actor_id -> Nullable<Text>,
resolver_name -> Nullable<Varchar>,
resolver_preferred_username -> Nullable<Varchar>,
resolver_avatar -> Nullable<Text>,
resolver_local -> Nullable<Bool>,
}
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Serialize)]
#[belongs_to(Comment)]
#[table_name = "comment_report"]
pub struct CommentReport {
pub id: i32,
pub creator_id: i32,
pub comment_id: i32,
pub original_comment_text: 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 = "comment_report"]
pub struct CommentReportForm {
pub creator_id: i32,
pub comment_id: i32,
pub original_comment_text: String,
pub reason: String,
}
impl Reportable<CommentReportForm> for CommentReport {
/// creates a comment report and returns it
///
/// * `conn` - the postgres connection
/// * `comment_report_form` - the filled CommentReportForm to insert
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)
}
/// resolve a comment 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: i32, by_resolver_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_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: i32, by_resolver_id: i32) -> Result<usize, Error> {
use crate::schema::comment_report::dsl::*;
update(comment_report.find(report_id))
.set((
resolved.eq(false),
resolver_id.eq(by_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
}
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, Clone)]
#[table_name = "comment_report_view"]
pub struct CommentReportView {
pub id: i32,
pub creator_id: i32,
pub comment_id: i32,
pub original_comment_text: String,
pub reason: String,
pub resolved: bool,
pub resolver_id: Option<i32>,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub post_id: i32,
pub current_comment_text: String,
pub community_id: i32,
pub creator_actor_id: String,
pub creator_name: String,
pub creator_preferred_username: Option<String>,
pub creator_avatar: Option<String>,
pub creator_local: bool,
pub comment_creator_id: i32,
pub comment_creator_actor_id: String,
pub comment_creator_name: String,
pub comment_creator_preferred_username: Option<String>,
pub comment_creator_avatar: Option<String>,
pub comment_creator_local: bool,
pub resolver_actor_id: Option<String>,
pub resolver_name: Option<String>,
pub resolver_preferred_username: Option<String>,
pub resolver_avatar: Option<String>,
pub resolver_local: Option<bool>,
}
pub struct CommentReportQueryBuilder<'a> {
conn: &'a PgConnection,
query: comment_report_view::BoxedQuery<'a, Pg>,
for_community_ids: Option<Vec<i32>>,
page: Option<i64>,
limit: Option<i64>,
resolved: Option<bool>,
}
impl CommentReportView {
/// returns the CommentReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
use super::comment_report::comment_report_view::dsl::*;
comment_report_view.find(report_id).first::<Self>(conn)
}
/// returns the current unresolved comment report count for the supplied community ids
///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use super::comment_report::comment_report_view::dsl::*;
comment_report_view
.filter(resolved.eq(false).and(community_id.eq_any(community_ids)))
.select(count(id))
.first::<i64>(conn)
}
}
impl<'a> CommentReportQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
use super::comment_report::comment_report_view::dsl::*;
let query = comment_report_view.into_boxed();
CommentReportQueryBuilder {
conn,
query,
for_community_ids: None,
page: None,
limit: None,
resolved: Some(false),
}
}
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 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 list(self) -> Result<Vec<CommentReportView>, Error> {
use super::comment_report::comment_report_view::dsl::*;
let mut query = self.query;
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 {
query = query.filter(resolved.eq(resolved_flag));
}
let (limit, offset) = limit_and_offset(self.page, self.limit);
query
.order_by(published.asc())
.limit(limit)
.offset(offset)
.load::<CommentReportView>(self.conn)
}
}

View File

@ -11,9 +11,6 @@ use regex::Regex;
use serde::{Deserialize, Serialize};
use std::{env, env::VarError};
pub mod comment_report;
pub mod post_report;
pub mod aggregates;
pub mod schema;
pub mod source;

View File

@ -1,245 +0,0 @@
use diesel::{dsl::*, pg::Pg, result::Error, *};
use serde::{Deserialize, Serialize};
use crate::{
limit_and_offset,
naive_now,
schema::post_report,
source::post::Post,
MaybeOptional,
Reportable,
};
table! {
post_report_view (id) {
id -> Int4,
creator_id -> Int4,
post_id -> Int4,
original_post_name -> Varchar,
original_post_url -> Nullable<Text>,
original_post_body -> Nullable<Text>,
reason -> Text,
resolved -> Bool,
resolver_id -> Nullable<Int4>,
published -> Timestamp,
updated -> Nullable<Timestamp>,
current_post_name -> Varchar,
current_post_url -> Nullable<Text>,
current_post_body -> Nullable<Text>,
community_id -> Int4,
creator_actor_id -> Text,
creator_name -> Varchar,
creator_preferred_username -> Nullable<Varchar>,
creator_avatar -> Nullable<Text>,
creator_local -> Bool,
post_creator_id -> Int4,
post_creator_actor_id -> Text,
post_creator_name -> Varchar,
post_creator_preferred_username -> Nullable<Varchar>,
post_creator_avatar -> Nullable<Text>,
post_creator_local -> Bool,
resolver_actor_id -> Nullable<Text>,
resolver_name -> Nullable<Varchar>,
resolver_preferred_username -> Nullable<Varchar>,
resolver_avatar -> Nullable<Text>,
resolver_local -> Nullable<Bool>,
}
}
#[derive(Identifiable, Queryable, Associations, PartialEq, Serialize, Deserialize, Debug)]
#[belongs_to(Post)]
#[table_name = "post_report"]
pub struct PostReport {
pub id: i32,
pub creator_id: i32,
pub post_id: i32,
pub original_post_name: String,
pub original_post_url: Option<String>,
pub original_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 original_post_name: String,
pub original_post_url: Option<String>,
pub original_post_body: Option<String>,
pub reason: String,
}
impl Reportable<PostReportForm> for PostReport {
/// creates a post report and returns it
///
/// * `conn` - the postgres connection
/// * `post_report_form` - the filled CommentReportForm to insert
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)
}
/// resolve a post 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: i32, by_resolver_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_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
/// resolve a post 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: i32, by_resolver_id: i32) -> Result<usize, Error> {
use crate::schema::post_report::dsl::*;
update(post_report.find(report_id))
.set((
resolved.eq(false),
resolver_id.eq(by_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
}
#[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize, Clone)]
#[table_name = "post_report_view"]
pub struct PostReportView {
pub id: i32,
pub creator_id: i32,
pub post_id: i32,
pub original_post_name: String,
pub original_post_url: Option<String>,
pub original_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 current_post_name: String,
pub current_post_url: Option<String>,
pub current_post_body: Option<String>,
pub community_id: i32,
pub creator_actor_id: String,
pub creator_name: String,
pub creator_preferred_username: Option<String>,
pub creator_avatar: Option<String>,
pub creator_local: bool,
pub post_creator_id: i32,
pub post_creator_actor_id: String,
pub post_creator_name: String,
pub post_creator_preferred_username: Option<String>,
pub post_creator_avatar: Option<String>,
pub post_creator_local: bool,
pub resolver_actor_id: Option<String>,
pub resolver_name: Option<String>,
pub resolver_preferred_username: Option<String>,
pub resolver_avatar: Option<String>,
pub resolver_local: Option<bool>,
}
impl PostReportView {
/// returns the PostReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
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)
}
/// returns the current unresolved post report count for the supplied community ids
///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use super::post_report::post_report_view::dsl::*;
post_report_view
.filter(resolved.eq(false).and(community_id.eq_any(community_ids)))
.select(count(id))
.first::<i64>(conn)
}
}
pub struct PostReportQueryBuilder<'a> {
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_ids: None,
page: None,
limit: None,
resolved: Some(false),
}
}
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 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 list(self) -> Result<Vec<PostReportView>, Error> {
use super::post_report::post_report_view::dsl::*;
let mut query = self.query;
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 {
query = query.filter(resolved.eq(resolved_flag));
}
let (limit, offset) = limit_and_offset(self.page, self.limit);
query
.order_by(published.asc())
.limit(limit)
.offset(offset)
.load::<PostReportView>(self.conn)
}
}

View File

@ -615,9 +615,45 @@ table! {
}
}
table! {
user_alias_2 (id) {
id -> Int4,
name -> Varchar,
preferred_username -> Nullable<Varchar>,
password_encrypted -> Text,
email -> Nullable<Text>,
avatar -> Nullable<Text>,
admin -> Bool,
banned -> Bool,
published -> Timestamp,
updated -> Nullable<Timestamp>,
show_nsfw -> Bool,
theme -> Varchar,
default_sort_type -> Int2,
default_listing_type -> Int2,
lang -> Varchar,
show_avatars -> Bool,
send_notifications_to_email -> Bool,
matrix_user_id -> Nullable<Text>,
actor_id -> Varchar,
bio -> Nullable<Text>,
local -> Bool,
private_key -> Nullable<Text>,
public_key -> Nullable<Text>,
last_refreshed_at -> Timestamp,
banner -> Nullable<Text>,
deleted -> Bool,
}
}
joinable!(comment_alias_1 -> user_alias_1 (creator_id));
joinable!(comment -> comment_alias_1 (parent_id));
joinable!(user_mention -> user_alias_1 (recipient_id));
joinable!(post -> user_alias_1 (creator_id));
joinable!(comment -> user_alias_1 (creator_id));
joinable!(post_report -> user_alias_2 (resolver_id));
joinable!(comment_report -> user_alias_2 (resolver_id));
joinable!(comment -> post (post_id));
joinable!(comment -> user_ (creator_id));
@ -708,4 +744,5 @@ allow_tables_to_appear_in_same_query!(
user_mention,
comment_alias_1,
user_alias_1,
user_alias_2,
);

View File

@ -0,0 +1,73 @@
use diesel::{dsl::*, result::Error, *};
use serde::{Deserialize, Serialize};
use crate::{naive_now, schema::comment_report, source::comment::Comment, Reportable};
#[derive(Identifiable, Queryable, Associations, PartialEq, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(Comment)]
#[table_name = "comment_report"]
pub struct CommentReport {
pub id: i32,
pub creator_id: i32,
pub comment_id: i32,
pub original_comment_text: 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 = "comment_report"]
pub struct CommentReportForm {
pub creator_id: i32,
pub comment_id: i32,
pub original_comment_text: String,
pub reason: String,
}
impl Reportable<CommentReportForm> for CommentReport {
/// creates a comment report and returns it
///
/// * `conn` - the postgres connection
/// * `comment_report_form` - the filled CommentReportForm to insert
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)
}
/// resolve a comment 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: i32, by_resolver_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_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: i32, by_resolver_id: i32) -> Result<usize, Error> {
use crate::schema::comment_report::dsl::*;
update(comment_report.find(report_id))
.set((
resolved.eq(false),
resolver_id.eq(by_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
}

View File

@ -1,10 +1,12 @@
pub mod activity;
pub mod category;
pub mod comment;
pub mod comment_report;
pub mod community;
pub mod moderator;
pub mod password_reset_request;
pub mod post;
pub mod post_report;
pub mod private_message;
pub mod site;
pub mod user;

View File

@ -0,0 +1,77 @@
use diesel::{dsl::*, result::Error, *};
use serde::{Deserialize, Serialize};
use crate::{naive_now, schema::post_report, source::post::Post, Reportable};
#[derive(Identifiable, Queryable, Associations, PartialEq, Serialize, Deserialize, Debug, Clone)]
#[belongs_to(Post)]
#[table_name = "post_report"]
pub struct PostReport {
pub id: i32,
pub creator_id: i32,
pub post_id: i32,
pub original_post_name: String,
pub original_post_url: Option<String>,
pub original_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 original_post_name: String,
pub original_post_url: Option<String>,
pub original_post_body: Option<String>,
pub reason: String,
}
impl Reportable<PostReportForm> for PostReport {
/// creates a post report and returns it
///
/// * `conn` - the postgres connection
/// * `post_report_form` - the filled CommentReportForm to insert
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)
}
/// resolve a post 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: i32, by_resolver_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_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
/// resolve a post 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: i32, by_resolver_id: i32) -> Result<usize, Error> {
use crate::schema::post_report::dsl::*;
update(post_report.find(report_id))
.set((
resolved.eq(false),
resolver_id.eq(by_resolver_id),
updated.eq(naive_now()),
))
.execute(conn)
}
}

View File

@ -1,7 +1,7 @@
use crate::{
is_email_regex,
naive_now,
schema::{user_, user_::dsl::*, user_alias_1},
schema::{user_, user_::dsl::*, user_alias_1, user_alias_2},
ApubObject,
Crud,
};
@ -153,7 +153,7 @@ pub struct UserSafeAlias1 {
pub deleted: bool,
}
mod safe_type_alias {
mod safe_type_alias_1 {
use crate::{schema::user_alias_1::columns::*, source::user::UserAlias1, ToSafe};
type Columns = (
id,
@ -195,6 +195,98 @@ mod safe_type_alias {
}
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"]
pub struct UserAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub password_encrypted: String,
pub email: Option<String>,
pub avatar: Option<String>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub show_nsfw: bool,
pub theme: String,
pub default_sort_type: i16,
pub default_listing_type: i16,
pub lang: String,
pub show_avatars: bool,
pub send_notifications_to_email: bool,
pub matrix_user_id: Option<String>,
pub actor_id: String,
pub bio: Option<String>,
pub local: bool,
pub private_key: Option<String>,
pub public_key: Option<String>,
pub last_refreshed_at: chrono::NaiveDateTime,
pub banner: Option<String>,
pub deleted: bool,
}
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
#[table_name = "user_alias_2"]
pub struct UserSafeAlias2 {
pub id: i32,
pub name: String,
pub preferred_username: Option<String>,
pub avatar: Option<String>,
pub admin: bool,
pub banned: bool,
pub published: chrono::NaiveDateTime,
pub updated: Option<chrono::NaiveDateTime>,
pub matrix_user_id: Option<String>,
pub actor_id: String,
pub bio: Option<String>,
pub local: bool,
pub banner: Option<String>,
pub deleted: bool,
}
mod safe_type_alias_2 {
use crate::{schema::user_alias_2::columns::*, source::user::UserAlias2, ToSafe};
type Columns = (
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
);
impl ToSafe for UserAlias2 {
type SafeColumns = Columns;
fn safe_columns_tuple() -> Self::SafeColumns {
(
id,
name,
preferred_username,
avatar,
admin,
banned,
published,
updated,
matrix_user_id,
actor_id,
bio,
local,
banner,
deleted,
)
}
}
}
#[derive(Insertable, AsChangeset, Clone)]
#[table_name = "user_"]
pub struct UserForm {

View File

@ -0,0 +1,193 @@
use crate::{
limit_and_offset,
schema::{comment, comment_report, community, post, user_, user_alias_1, user_alias_2},
source::{
comment::Comment,
comment_report::CommentReport,
community::{Community, CommunitySafe},
post::Post,
user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_},
},
views::ViewToVec,
MaybeOptional,
ToSafe,
};
use diesel::{result::Error, *};
use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)]
pub struct CommentReportView {
pub comment_report: CommentReport,
pub comment: Comment,
pub post: Post,
pub community: CommunitySafe,
pub creator: UserSafe,
pub comment_creator: UserSafeAlias1,
pub resolver: Option<UserSafeAlias2>,
}
type CommentReportViewTuple = (
CommentReport,
Comment,
Post,
CommunitySafe,
UserSafe,
UserSafeAlias1,
Option<UserSafeAlias2>,
);
impl CommentReportView {
/// returns the CommentReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
let (comment_report, comment, post, community, creator, comment_creator, resolver) =
comment_report::table
.find(report_id)
.inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(comment_report::creator_id.eq(user_::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id)))
.left_join(
user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())),
)
.select((
comment_report::all_columns,
comment::all_columns,
post::all_columns,
Community::safe_columns_tuple(),
User_::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(),
))
.first::<CommentReportViewTuple>(conn)?;
Ok(Self {
comment_report,
comment,
post,
community,
creator,
comment_creator,
resolver,
})
}
/// returns the current unresolved post report count for the supplied community ids
///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for
/// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
/// for a user id
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use diesel::dsl::*;
comment_report::table
.inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id)))
.filter(
comment_report::resolved
.eq(false)
.and(post::community_id.eq_any(community_ids)),
)
.select(count(comment_report::id))
.first::<i64>(conn)
}
}
pub struct CommentReportQueryBuilder<'a> {
conn: &'a PgConnection,
community_ids: Option<Vec<i32>>, // TODO bad way to do this
page: Option<i64>,
limit: Option<i64>,
resolved: Option<bool>,
}
impl<'a> CommentReportQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
CommentReportQueryBuilder {
conn,
community_ids: None,
page: None,
limit: None,
resolved: Some(false),
}
}
pub fn community_ids<T: MaybeOptional<Vec<i32>>>(mut self, community_ids: T) -> Self {
self.community_ids = community_ids.get_optional();
self
}
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 list(self) -> Result<Vec<CommentReportView>, Error> {
let mut query = comment_report::table
.inner_join(comment::table)
.inner_join(post::table.on(comment::post_id.eq(post::id)))
.inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(comment_report::creator_id.eq(user_::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id)))
.left_join(
user_alias_2::table.on(comment_report::resolver_id.eq(user_alias_2::id.nullable())),
)
.select((
comment_report::all_columns,
comment::all_columns,
post::all_columns,
Community::safe_columns_tuple(),
User_::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(),
))
.into_boxed();
if let Some(comm_ids) = self.community_ids {
query = query.filter(post::community_id.eq_any(comm_ids));
}
if let Some(resolved_flag) = self.resolved {
query = query.filter(comment_report::resolved.eq(resolved_flag));
}
let (limit, offset) = limit_and_offset(self.page, self.limit);
let res = query
.order_by(comment_report::published.asc())
.limit(limit)
.offset(offset)
.load::<CommentReportViewTuple>(self.conn)?;
Ok(CommentReportView::to_vec(res))
}
}
impl ViewToVec for CommentReportView {
type DbTuple = CommentReportViewTuple;
fn to_vec(posts: Vec<Self::DbTuple>) -> Vec<Self> {
posts
.iter()
.map(|a| Self {
comment_report: a.0.to_owned(),
comment: a.1.to_owned(),
post: a.2.to_owned(),
community: a.3.to_owned(),
creator: a.4.to_owned(),
comment_creator: a.5.to_owned(),
resolver: a.6.to_owned(),
})
.collect::<Vec<Self>>()
}
}

View File

@ -1,6 +1,8 @@
pub mod comment_report_view;
pub mod comment_view;
pub mod community;
pub mod moderator;
pub mod post_report_view;
pub mod post_view;
pub mod private_message_view;
pub mod site_view;

View File

@ -0,0 +1,178 @@
use crate::{
limit_and_offset,
schema::{community, post, post_report, user_, user_alias_1, user_alias_2},
source::{
community::{Community, CommunitySafe},
post::Post,
post_report::PostReport,
user::{UserAlias1, UserAlias2, UserSafe, UserSafeAlias1, UserSafeAlias2, User_},
},
views::ViewToVec,
MaybeOptional,
ToSafe,
};
use diesel::{result::Error, *};
use serde::Serialize;
#[derive(Debug, PartialEq, Serialize, Clone)]
pub struct PostReportView {
pub post_report: PostReport,
pub post: Post,
pub community: CommunitySafe,
pub creator: UserSafe,
pub post_creator: UserSafeAlias1,
pub resolver: Option<UserSafeAlias2>,
}
type PostReportViewTuple = (
PostReport,
Post,
CommunitySafe,
UserSafe,
UserSafeAlias1,
Option<UserSafeAlias2>,
);
impl PostReportView {
/// returns the PostReportView for the provided report_id
///
/// * `report_id` - the report id to obtain
pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
let (post_report, post, community, creator, post_creator, resolver) = post_report::table
.find(report_id)
.inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(post_report::creator_id.eq(user_::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id)))
.left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable())))
.select((
post_report::all_columns,
post::all_columns,
Community::safe_columns_tuple(),
User_::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(),
))
.first::<PostReportViewTuple>(conn)?;
Ok(Self {
post_report,
post,
community,
creator,
post_creator,
resolver,
})
}
/// returns the current unresolved post report count for the supplied community ids
///
/// * `community_ids` - a Vec<i32> of community_ids to get a count for
/// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
/// for a user id
pub fn get_report_count(conn: &PgConnection, community_ids: &[i32]) -> Result<i64, Error> {
use diesel::dsl::*;
post_report::table
.inner_join(post::table)
.filter(
post_report::resolved
.eq(false)
.and(post::community_id.eq_any(community_ids)),
)
.select(count(post_report::id))
.first::<i64>(conn)
}
}
pub struct PostReportQueryBuilder<'a> {
conn: &'a PgConnection,
community_ids: Option<Vec<i32>>, // TODO bad way to do this
page: Option<i64>,
limit: Option<i64>,
resolved: Option<bool>,
}
impl<'a> PostReportQueryBuilder<'a> {
pub fn create(conn: &'a PgConnection) -> Self {
PostReportQueryBuilder {
conn,
community_ids: None,
page: None,
limit: None,
resolved: Some(false),
}
}
pub fn community_ids<T: MaybeOptional<Vec<i32>>>(mut self, community_ids: T) -> Self {
self.community_ids = community_ids.get_optional();
self
}
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 list(self) -> Result<Vec<PostReportView>, Error> {
let mut query = post_report::table
.inner_join(post::table)
.inner_join(community::table.on(post::community_id.eq(community::id)))
.inner_join(user_::table.on(post_report::creator_id.eq(user_::id)))
.inner_join(user_alias_1::table.on(post::creator_id.eq(user_alias_1::id)))
.left_join(user_alias_2::table.on(post_report::resolver_id.eq(user_alias_2::id.nullable())))
.select((
post_report::all_columns,
post::all_columns,
Community::safe_columns_tuple(),
User_::safe_columns_tuple(),
UserAlias1::safe_columns_tuple(),
UserAlias2::safe_columns_tuple().nullable(),
))
.into_boxed();
if let Some(comm_ids) = self.community_ids {
query = query.filter(post::community_id.eq_any(comm_ids));
}
if let Some(resolved_flag) = self.resolved {
query = query.filter(post_report::resolved.eq(resolved_flag));
}
let (limit, offset) = limit_and_offset(self.page, self.limit);
let res = query
.order_by(post_report::published.asc())
.limit(limit)
.offset(offset)
.load::<PostReportViewTuple>(self.conn)?;
Ok(PostReportView::to_vec(res))
}
}
impl ViewToVec for PostReportView {
type DbTuple = PostReportViewTuple;
fn to_vec(posts: Vec<Self::DbTuple>) -> Vec<Self> {
posts
.iter()
.map(|a| Self {
post_report: a.0.to_owned(),
post: a.1.to_owned(),
community: a.2.to_owned(),
creator: a.3.to_owned(),
post_creator: a.4.to_owned(),
resolver: a.5.to_owned(),
})
.collect::<Vec<Self>>()
}
}

View File

@ -1,4 +1,4 @@
use lemmy_db::{comment_report::CommentReportView, views::comment_view::CommentView};
use lemmy_db::views::{comment_report_view::CommentReportView, comment_view::CommentView};
use serde::{Deserialize, Serialize};
#[derive(Deserialize)]
@ -111,7 +111,7 @@ pub struct ListCommentReports {
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Clone, Debug)]
pub struct ListCommentReportsResponse {
pub comments: Vec<CommentReportView>,
}

View File

@ -1,10 +1,8 @@
use lemmy_db::{
post_report::PostReportView,
views::{
comment_view::CommentView,
community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
post_view::PostView,
},
use lemmy_db::views::{
comment_view::CommentView,
community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
post_report_view::PostReportView,
post_view::PostView,
};
use serde::{Deserialize, Serialize};
@ -150,7 +148,7 @@ pub struct ListPostReports {
pub auth: String,
}
#[derive(Serialize, Deserialize, Clone, Debug)]
#[derive(Serialize, Clone, Debug)]
pub struct ListPostReportsResponse {
pub posts: Vec<PostReportView>,
}