]> Untitled Git - lemmy.git/blob - crates/db_schema/src/traits.rs
Automatically resolve report when post/comment is removed (#3850)
[lemmy.git] / crates / db_schema / src / traits.rs
1 use crate::{
2   newtypes::{CommunityId, DbUrl, PersonId},
3   utils::{get_conn, DbPool},
4 };
5 use diesel::{
6   associations::HasTable,
7   dsl,
8   query_builder::{DeleteStatement, IntoUpdateTarget},
9   query_dsl::methods::{FindDsl, LimitDsl},
10   result::Error,
11   Table,
12 };
13 use diesel_async::{
14   methods::{ExecuteDsl, LoadQuery},
15   AsyncPgConnection,
16   RunQueryDsl,
17 };
18
19 /// Returned by `diesel::delete`
20 pub type Delete<T> = DeleteStatement<<T as HasTable>::Table, <T as IntoUpdateTarget>::WhereClause>;
21
22 /// Returned by `Self::table().find(id)`
23 pub type Find<T> = dsl::Find<<T as HasTable>::Table, <T as Crud>::IdType>;
24
25 pub type PrimaryKey<T> = <<T as HasTable>::Table as Table>::PrimaryKey;
26
27 // Trying to create default implementations for `create` and `update` results in a lifetime mess and weird compile errors.
28 // https://github.com/rust-lang/rust/issues/102211
29 #[async_trait]
30 pub trait Crud: HasTable + Sized
31 where
32   Self::Table: FindDsl<Self::IdType>,
33   Find<Self>: LimitDsl + IntoUpdateTarget + Send,
34   Delete<Find<Self>>: ExecuteDsl<AsyncPgConnection> + Send + 'static,
35
36   // Used by `RunQueryDsl::first`
37   dsl::Limit<Find<Self>>: LoadQuery<'static, AsyncPgConnection, Self> + Send + 'static,
38 {
39   type InsertForm;
40   type UpdateForm;
41   type IdType: Send;
42
43   async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error>;
44
45   async fn read(pool: &mut DbPool<'_>, id: Self::IdType) -> Result<Self, Error> {
46     let query: Find<Self> = Self::table().find(id);
47     let conn = &mut *get_conn(pool).await?;
48     query.first::<Self>(conn).await
49   }
50
51   /// when you want to null out a column, you have to send Some(None)), since sending None means you just don't want to update that column.
52   async fn update(
53     pool: &mut DbPool<'_>,
54     id: Self::IdType,
55     form: &Self::UpdateForm,
56   ) -> Result<Self, Error>;
57
58   async fn delete(pool: &mut DbPool<'_>, id: Self::IdType) -> Result<usize, Error> {
59     let query: Delete<Find<Self>> = diesel::delete(Self::table().find(id));
60     let conn = &mut *get_conn(pool).await?;
61     query.execute(conn).await
62   }
63 }
64
65 #[async_trait]
66 pub trait Followable {
67   type Form;
68   async fn follow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
69   where
70     Self: Sized;
71   async fn follow_accepted(
72     pool: &mut DbPool<'_>,
73     community_id: CommunityId,
74     person_id: PersonId,
75   ) -> Result<Self, Error>
76   where
77     Self: Sized;
78   async fn unfollow(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
79   where
80     Self: Sized;
81 }
82
83 #[async_trait]
84 pub trait Joinable {
85   type Form;
86   async fn join(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
87   where
88     Self: Sized;
89   async fn leave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
90   where
91     Self: Sized;
92 }
93
94 #[async_trait]
95 pub trait Likeable {
96   type Form;
97   type IdType;
98   async fn like(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
99   where
100     Self: Sized;
101   async fn remove(
102     pool: &mut DbPool<'_>,
103     person_id: PersonId,
104     item_id: Self::IdType,
105   ) -> Result<usize, Error>
106   where
107     Self: Sized;
108 }
109
110 #[async_trait]
111 pub trait Bannable {
112   type Form;
113   async fn ban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
114   where
115     Self: Sized;
116   async fn unban(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
117   where
118     Self: Sized;
119 }
120
121 #[async_trait]
122 pub trait Saveable {
123   type Form;
124   async fn save(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
125   where
126     Self: Sized;
127   async fn unsave(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
128   where
129     Self: Sized;
130 }
131
132 #[async_trait]
133 pub trait Blockable {
134   type Form;
135   async fn block(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
136   where
137     Self: Sized;
138   async fn unblock(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
139   where
140     Self: Sized;
141 }
142
143 #[async_trait]
144 pub trait Readable {
145   type Form;
146   async fn mark_as_read(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
147   where
148     Self: Sized;
149   async fn mark_as_unread(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<usize, Error>
150   where
151     Self: Sized;
152 }
153
154 #[async_trait]
155 pub trait Reportable {
156   type Form;
157   type IdType;
158   type ObjectIdType;
159   async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> Result<Self, Error>
160   where
161     Self: Sized;
162   async fn resolve(
163     pool: &mut DbPool<'_>,
164     report_id: Self::IdType,
165     resolver_id: PersonId,
166   ) -> Result<usize, Error>
167   where
168     Self: Sized;
169   async fn resolve_all_for_object(
170     pool: &mut DbPool<'_>,
171     comment_id_: Self::ObjectIdType,
172     by_resolver_id: PersonId,
173   ) -> Result<usize, Error>
174   where
175     Self: Sized;
176   async fn unresolve(
177     pool: &mut DbPool<'_>,
178     report_id: Self::IdType,
179     resolver_id: PersonId,
180   ) -> Result<usize, Error>
181   where
182     Self: Sized;
183 }
184
185 pub trait JoinView {
186   type JoinTuple;
187   fn from_tuple(tuple: Self::JoinTuple) -> Self
188   where
189     Self: Sized;
190 }
191
192 #[async_trait]
193 pub trait ApubActor {
194   async fn read_from_apub_id(
195     pool: &mut DbPool<'_>,
196     object_id: &DbUrl,
197   ) -> Result<Option<Self>, Error>
198   where
199     Self: Sized;
200   /// - actor_name is the name of the community or user to read.
201   /// - include_deleted, if true, will return communities or users that were deleted/removed
202   async fn read_from_name(
203     pool: &mut DbPool<'_>,
204     actor_name: &str,
205     include_deleted: bool,
206   ) -> Result<Self, Error>
207   where
208     Self: Sized;
209   async fn read_from_name_and_domain(
210     pool: &mut DbPool<'_>,
211     actor_name: &str,
212     protocol_domain: &str,
213   ) -> Result<Self, Error>
214   where
215     Self: Sized;
216 }