]> Untitled Git - lemmy.git/blob - server/src/db/community.rs
Merge branch 'dev' into federation
[lemmy.git] / server / src / db / community.rs
1 use super::*;
2 use crate::schema::{community, community_follower, community_moderator, community_user_ban};
3
4 #[derive(Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)]
5 #[table_name = "community"]
6 pub struct Community {
7   pub id: i32,
8   pub name: String,
9   pub title: String,
10   pub description: Option<String>,
11   pub category_id: i32,
12   pub creator_id: i32,
13   pub removed: bool,
14   pub published: chrono::NaiveDateTime,
15   pub updated: Option<chrono::NaiveDateTime>,
16   pub deleted: bool,
17   pub nsfw: bool,
18   pub actor_id: String,
19   pub local: bool,
20   pub private_key: Option<String>,
21   pub public_key: Option<String>,
22   pub last_refreshed_at: chrono::NaiveDateTime,
23 }
24
25 #[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize, Debug)]
26 #[table_name = "community"]
27 pub struct CommunityForm {
28   pub name: String,
29   pub title: String,
30   pub description: Option<String>,
31   pub category_id: i32,
32   pub creator_id: i32,
33   pub removed: Option<bool>,
34   pub published: Option<chrono::NaiveDateTime>,
35   pub updated: Option<chrono::NaiveDateTime>,
36   pub deleted: Option<bool>,
37   pub nsfw: bool,
38   pub actor_id: String,
39   pub local: bool,
40   pub private_key: Option<String>,
41   pub public_key: Option<String>,
42   pub last_refreshed_at: Option<chrono::NaiveDateTime>,
43 }
44
45 impl Crud<CommunityForm> for Community {
46   fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> {
47     use crate::schema::community::dsl::*;
48     community.find(community_id).first::<Self>(conn)
49   }
50
51   fn delete(conn: &PgConnection, community_id: i32) -> Result<usize, Error> {
52     use crate::schema::community::dsl::*;
53     diesel::delete(community.find(community_id)).execute(conn)
54   }
55
56   fn create(conn: &PgConnection, new_community: &CommunityForm) -> Result<Self, Error> {
57     use crate::schema::community::dsl::*;
58     insert_into(community)
59       .values(new_community)
60       .get_result::<Self>(conn)
61   }
62
63   fn update(
64     conn: &PgConnection,
65     community_id: i32,
66     new_community: &CommunityForm,
67   ) -> Result<Self, Error> {
68     use crate::schema::community::dsl::*;
69     diesel::update(community.find(community_id))
70       .set(new_community)
71       .get_result::<Self>(conn)
72   }
73 }
74
75 impl Community {
76   pub fn read_from_name(conn: &PgConnection, community_name: String) -> Result<Self, Error> {
77     use crate::schema::community::dsl::*;
78     community
79       .filter(name.eq(community_name))
80       .first::<Self>(conn)
81   }
82
83   pub fn read_from_actor_id(conn: &PgConnection, community_id: &str) -> Result<Self, Error> {
84     use crate::schema::community::dsl::*;
85     community
86       .filter(actor_id.eq(community_id))
87       .first::<Self>(conn)
88   }
89
90   pub fn list_local(conn: &PgConnection) -> Result<Vec<Self>, Error> {
91     use crate::schema::community::dsl::*;
92     community.filter(local.eq(true)).load::<Community>(conn)
93   }
94
95   pub fn get_url(&self) -> String {
96     format!("https://{}/c/{}", Settings::get().hostname, self.name)
97   }
98 }
99
100 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
101 #[belongs_to(Community)]
102 #[table_name = "community_moderator"]
103 pub struct CommunityModerator {
104   pub id: i32,
105   pub community_id: i32,
106   pub user_id: i32,
107   pub published: chrono::NaiveDateTime,
108 }
109
110 #[derive(Insertable, AsChangeset, Clone)]
111 #[table_name = "community_moderator"]
112 pub struct CommunityModeratorForm {
113   pub community_id: i32,
114   pub user_id: i32,
115 }
116
117 impl Joinable<CommunityModeratorForm> for CommunityModerator {
118   fn join(
119     conn: &PgConnection,
120     community_user_form: &CommunityModeratorForm,
121   ) -> Result<Self, Error> {
122     use crate::schema::community_moderator::dsl::*;
123     insert_into(community_moderator)
124       .values(community_user_form)
125       .get_result::<Self>(conn)
126   }
127
128   fn leave(
129     conn: &PgConnection,
130     community_user_form: &CommunityModeratorForm,
131   ) -> Result<usize, Error> {
132     use crate::schema::community_moderator::dsl::*;
133     diesel::delete(
134       community_moderator
135         .filter(community_id.eq(community_user_form.community_id))
136         .filter(user_id.eq(community_user_form.user_id)),
137     )
138     .execute(conn)
139   }
140 }
141
142 impl CommunityModerator {
143   pub fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error> {
144     use crate::schema::community_moderator::dsl::*;
145     diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
146   }
147 }
148
149 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
150 #[belongs_to(Community)]
151 #[table_name = "community_user_ban"]
152 pub struct CommunityUserBan {
153   pub id: i32,
154   pub community_id: i32,
155   pub user_id: i32,
156   pub published: chrono::NaiveDateTime,
157 }
158
159 #[derive(Insertable, AsChangeset, Clone)]
160 #[table_name = "community_user_ban"]
161 pub struct CommunityUserBanForm {
162   pub community_id: i32,
163   pub user_id: i32,
164 }
165
166 impl Bannable<CommunityUserBanForm> for CommunityUserBan {
167   fn ban(
168     conn: &PgConnection,
169     community_user_ban_form: &CommunityUserBanForm,
170   ) -> Result<Self, Error> {
171     use crate::schema::community_user_ban::dsl::*;
172     insert_into(community_user_ban)
173       .values(community_user_ban_form)
174       .get_result::<Self>(conn)
175   }
176
177   fn unban(
178     conn: &PgConnection,
179     community_user_ban_form: &CommunityUserBanForm,
180   ) -> Result<usize, Error> {
181     use crate::schema::community_user_ban::dsl::*;
182     diesel::delete(
183       community_user_ban
184         .filter(community_id.eq(community_user_ban_form.community_id))
185         .filter(user_id.eq(community_user_ban_form.user_id)),
186     )
187     .execute(conn)
188   }
189 }
190
191 #[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
192 #[belongs_to(Community)]
193 #[table_name = "community_follower"]
194 pub struct CommunityFollower {
195   pub id: i32,
196   pub community_id: i32,
197   pub user_id: i32,
198   pub published: chrono::NaiveDateTime,
199 }
200
201 #[derive(Insertable, AsChangeset, Clone)]
202 #[table_name = "community_follower"]
203 pub struct CommunityFollowerForm {
204   pub community_id: i32,
205   pub user_id: i32,
206 }
207
208 impl Followable<CommunityFollowerForm> for CommunityFollower {
209   fn follow(
210     conn: &PgConnection,
211     community_follower_form: &CommunityFollowerForm,
212   ) -> Result<Self, Error> {
213     use crate::schema::community_follower::dsl::*;
214     insert_into(community_follower)
215       .values(community_follower_form)
216       .get_result::<Self>(conn)
217   }
218   fn ignore(
219     conn: &PgConnection,
220     community_follower_form: &CommunityFollowerForm,
221   ) -> Result<usize, Error> {
222     use crate::schema::community_follower::dsl::*;
223     diesel::delete(
224       community_follower
225         .filter(community_id.eq(&community_follower_form.community_id))
226         .filter(user_id.eq(&community_follower_form.user_id)),
227     )
228     .execute(conn)
229   }
230 }
231
232 #[cfg(test)]
233 mod tests {
234   use super::super::user::*;
235   use super::*;
236   #[test]
237   fn test_crud() {
238     let conn = establish_unpooled_connection();
239
240     let new_user = UserForm {
241       name: "bobbee".into(),
242       preferred_username: None,
243       password_encrypted: "nope".into(),
244       email: None,
245       matrix_user_id: None,
246       avatar: None,
247       admin: false,
248       banned: false,
249       updated: None,
250       show_nsfw: false,
251       theme: "darkly".into(),
252       default_sort_type: SortType::Hot as i16,
253       default_listing_type: ListingType::Subscribed as i16,
254       lang: "browser".into(),
255       show_avatars: true,
256       send_notifications_to_email: false,
257       actor_id: "changeme".into(),
258       bio: None,
259       local: true,
260       private_key: None,
261       public_key: None,
262       last_refreshed_at: None,
263     };
264
265     let inserted_user = User_::create(&conn, &new_user).unwrap();
266
267     let new_community = CommunityForm {
268       name: "TIL".into(),
269       creator_id: inserted_user.id,
270       title: "nada".to_owned(),
271       description: None,
272       category_id: 1,
273       nsfw: false,
274       removed: None,
275       deleted: None,
276       updated: None,
277       actor_id: "changeme".into(),
278       local: true,
279       private_key: None,
280       public_key: None,
281       last_refreshed_at: None,
282       published: None,
283     };
284
285     let inserted_community = Community::create(&conn, &new_community).unwrap();
286
287     let expected_community = Community {
288       id: inserted_community.id,
289       creator_id: inserted_user.id,
290       name: "TIL".into(),
291       title: "nada".to_owned(),
292       description: None,
293       category_id: 1,
294       nsfw: false,
295       removed: false,
296       deleted: false,
297       published: inserted_community.published,
298       updated: None,
299       actor_id: "changeme".into(),
300       local: true,
301       private_key: None,
302       public_key: None,
303       last_refreshed_at: inserted_community.published,
304     };
305
306     let community_follower_form = CommunityFollowerForm {
307       community_id: inserted_community.id,
308       user_id: inserted_user.id,
309     };
310
311     let inserted_community_follower =
312       CommunityFollower::follow(&conn, &community_follower_form).unwrap();
313
314     let expected_community_follower = CommunityFollower {
315       id: inserted_community_follower.id,
316       community_id: inserted_community.id,
317       user_id: inserted_user.id,
318       published: inserted_community_follower.published,
319     };
320
321     let community_user_form = CommunityModeratorForm {
322       community_id: inserted_community.id,
323       user_id: inserted_user.id,
324     };
325
326     let inserted_community_user = CommunityModerator::join(&conn, &community_user_form).unwrap();
327
328     let expected_community_user = CommunityModerator {
329       id: inserted_community_user.id,
330       community_id: inserted_community.id,
331       user_id: inserted_user.id,
332       published: inserted_community_user.published,
333     };
334
335     let community_user_ban_form = CommunityUserBanForm {
336       community_id: inserted_community.id,
337       user_id: inserted_user.id,
338     };
339
340     let inserted_community_user_ban =
341       CommunityUserBan::ban(&conn, &community_user_ban_form).unwrap();
342
343     let expected_community_user_ban = CommunityUserBan {
344       id: inserted_community_user_ban.id,
345       community_id: inserted_community.id,
346       user_id: inserted_user.id,
347       published: inserted_community_user_ban.published,
348     };
349
350     let read_community = Community::read(&conn, inserted_community.id).unwrap();
351     let updated_community =
352       Community::update(&conn, inserted_community.id, &new_community).unwrap();
353     let ignored_community = CommunityFollower::ignore(&conn, &community_follower_form).unwrap();
354     let left_community = CommunityModerator::leave(&conn, &community_user_form).unwrap();
355     let unban = CommunityUserBan::unban(&conn, &community_user_ban_form).unwrap();
356     let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
357     User_::delete(&conn, inserted_user.id).unwrap();
358
359     assert_eq!(expected_community, read_community);
360     assert_eq!(expected_community, inserted_community);
361     assert_eq!(expected_community, updated_community);
362     assert_eq!(expected_community_follower, inserted_community_follower);
363     assert_eq!(expected_community_user, inserted_community_user);
364     assert_eq!(expected_community_user_ban, inserted_community_user_ban);
365     assert_eq!(1, ignored_community);
366     assert_eq!(1, left_community);
367     assert_eq!(1, unban);
368     // assert_eq!(2, loaded_count);
369     assert_eq!(1, num_deleted);
370   }
371 }