]> Untitled Git - lemmy.git/blob - crates/db_views/src/post_report_view.rs
Merge branch 'split_user_table' into strictly_type_db_ids
[lemmy.git] / crates / db_views / src / post_report_view.rs
1 use diesel::{result::Error, *};
2 use lemmy_db_queries::{limit_and_offset, MaybeOptional, ToSafe, ViewToVec};
3 use lemmy_db_schema::{
4   schema::{community, person, person_alias_1, person_alias_2, post, post_report},
5   source::{
6     community::{Community, CommunitySafe},
7     person::{Person, PersonAlias1, PersonAlias2, PersonSafe, PersonSafeAlias1, PersonSafeAlias2},
8     post::Post,
9     post_report::PostReport,
10   },
11   CommunityId,
12 };
13 use serde::Serialize;
14
15 #[derive(Debug, PartialEq, Serialize, Clone)]
16 pub struct PostReportView {
17   pub post_report: PostReport,
18   pub post: Post,
19   pub community: CommunitySafe,
20   pub creator: PersonSafe,
21   pub post_creator: PersonSafeAlias1,
22   pub resolver: Option<PersonSafeAlias2>,
23 }
24
25 type PostReportViewTuple = (
26   PostReport,
27   Post,
28   CommunitySafe,
29   PersonSafe,
30   PersonSafeAlias1,
31   Option<PersonSafeAlias2>,
32 );
33
34 impl PostReportView {
35   /// returns the PostReportView for the provided report_id
36   ///
37   /// * `report_id` - the report id to obtain
38   pub fn read(conn: &PgConnection, report_id: i32) -> Result<Self, Error> {
39     let (post_report, post, community, creator, post_creator, resolver) = post_report::table
40       .find(report_id)
41       .inner_join(post::table)
42       .inner_join(community::table.on(post::community_id.eq(community::id)))
43       .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
44       .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
45       .left_join(
46         person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
47       )
48       .select((
49         post_report::all_columns,
50         post::all_columns,
51         Community::safe_columns_tuple(),
52         Person::safe_columns_tuple(),
53         PersonAlias1::safe_columns_tuple(),
54         PersonAlias2::safe_columns_tuple().nullable(),
55       ))
56       .first::<PostReportViewTuple>(conn)?;
57
58     Ok(Self {
59       post_report,
60       post,
61       community,
62       creator,
63       post_creator,
64       resolver,
65     })
66   }
67
68   /// returns the current unresolved post report count for the supplied community ids
69   ///
70   /// * `community_ids` - a Vec<i32> of community_ids to get a count for
71   /// TODO this eq_any is a bad way to do this, would be better to join to communitymoderator
72   /// for a person id
73   pub fn get_report_count(
74     conn: &PgConnection,
75     community_ids: &[CommunityId],
76   ) -> Result<i64, Error> {
77     use diesel::dsl::*;
78     post_report::table
79       .inner_join(post::table)
80       .filter(
81         post_report::resolved
82           .eq(false)
83           .and(post::community_id.eq_any(community_ids)),
84       )
85       .select(count(post_report::id))
86       .first::<i64>(conn)
87   }
88 }
89
90 pub struct PostReportQueryBuilder<'a> {
91   conn: &'a PgConnection,
92   community_ids: Option<Vec<CommunityId>>, // TODO bad way to do this
93   page: Option<i64>,
94   limit: Option<i64>,
95   resolved: Option<bool>,
96 }
97
98 impl<'a> PostReportQueryBuilder<'a> {
99   pub fn create(conn: &'a PgConnection) -> Self {
100     PostReportQueryBuilder {
101       conn,
102       community_ids: None,
103       page: None,
104       limit: None,
105       resolved: Some(false),
106     }
107   }
108
109   pub fn community_ids<T: MaybeOptional<Vec<CommunityId>>>(mut self, community_ids: T) -> Self {
110     self.community_ids = community_ids.get_optional();
111     self
112   }
113
114   pub fn page<T: MaybeOptional<i64>>(mut self, page: T) -> Self {
115     self.page = page.get_optional();
116     self
117   }
118
119   pub fn limit<T: MaybeOptional<i64>>(mut self, limit: T) -> Self {
120     self.limit = limit.get_optional();
121     self
122   }
123
124   pub fn resolved<T: MaybeOptional<bool>>(mut self, resolved: T) -> Self {
125     self.resolved = resolved.get_optional();
126     self
127   }
128
129   pub fn list(self) -> Result<Vec<PostReportView>, Error> {
130     let mut query = post_report::table
131       .inner_join(post::table)
132       .inner_join(community::table.on(post::community_id.eq(community::id)))
133       .inner_join(person::table.on(post_report::creator_id.eq(person::id)))
134       .inner_join(person_alias_1::table.on(post::creator_id.eq(person_alias_1::id)))
135       .left_join(
136         person_alias_2::table.on(post_report::resolver_id.eq(person_alias_2::id.nullable())),
137       )
138       .select((
139         post_report::all_columns,
140         post::all_columns,
141         Community::safe_columns_tuple(),
142         Person::safe_columns_tuple(),
143         PersonAlias1::safe_columns_tuple(),
144         PersonAlias2::safe_columns_tuple().nullable(),
145       ))
146       .into_boxed();
147
148     if let Some(comm_ids) = self.community_ids {
149       query = query.filter(post::community_id.eq_any(comm_ids));
150     }
151
152     if let Some(resolved_flag) = self.resolved {
153       query = query.filter(post_report::resolved.eq(resolved_flag));
154     }
155
156     let (limit, offset) = limit_and_offset(self.page, self.limit);
157
158     let res = query
159       .order_by(post_report::published.asc())
160       .limit(limit)
161       .offset(offset)
162       .load::<PostReportViewTuple>(self.conn)?;
163
164     Ok(PostReportView::from_tuple_to_vec(res))
165   }
166 }
167
168 impl ViewToVec for PostReportView {
169   type DbTuple = PostReportViewTuple;
170   fn from_tuple_to_vec(items: Vec<Self::DbTuple>) -> Vec<Self> {
171     items
172       .iter()
173       .map(|a| Self {
174         post_report: a.0.to_owned(),
175         post: a.1.to_owned(),
176         community: a.2.to_owned(),
177         creator: a.3.to_owned(),
178         post_creator: a.4.to_owned(),
179         resolver: a.5.to_owned(),
180       })
181       .collect::<Vec<Self>>()
182   }
183 }