1 use crate::{ApubObject, Bannable, Crud, DeleteableOrRemoveable, Followable, Joinable};
2 use chrono::NaiveDateTime;
3 use diesel::{dsl::*, result::Error, *};
12 CommunityModeratorForm,
14 CommunityPersonBanForm,
23 use crate::{source::community::Community, ToSafe};
24 use lemmy_db_schema::schema::community::*;
42 impl ToSafe for Community {
43 type SafeColumns = Columns;
44 fn safe_columns_tuple() -> Self::SafeColumns {
64 impl Crud for Community {
65 type Form = CommunityForm;
66 type IdType = CommunityId;
67 fn read(conn: &PgConnection, community_id: CommunityId) -> Result<Self, Error> {
68 use lemmy_db_schema::schema::community::dsl::*;
69 community.find(community_id).first::<Self>(conn)
72 fn delete(conn: &PgConnection, community_id: CommunityId) -> Result<usize, Error> {
73 use lemmy_db_schema::schema::community::dsl::*;
74 diesel::delete(community.find(community_id)).execute(conn)
77 fn create(conn: &PgConnection, new_community: &CommunityForm) -> Result<Self, Error> {
78 use lemmy_db_schema::schema::community::dsl::*;
79 insert_into(community)
80 .values(new_community)
81 .get_result::<Self>(conn)
86 community_id: CommunityId,
87 new_community: &CommunityForm,
88 ) -> Result<Self, Error> {
89 use lemmy_db_schema::schema::community::dsl::*;
90 diesel::update(community.find(community_id))
92 .get_result::<Self>(conn)
96 impl ApubObject for Community {
97 fn last_refreshed_at(&self) -> Option<NaiveDateTime> {
98 Some(self.last_refreshed_at)
101 fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result<Self, Error> {
102 use lemmy_db_schema::schema::community::dsl::*;
104 .filter(actor_id.eq(for_actor_id))
109 pub trait Community_ {
110 fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error>;
113 community_id: CommunityId,
115 ) -> Result<Community, Error>;
118 community_id: CommunityId,
120 ) -> Result<Community, Error>;
121 fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error>;
122 fn read_from_followers_url(
124 followers_url: &DbUrl,
125 ) -> Result<Community, Error>;
126 fn upsert(conn: &PgConnection, community_form: &CommunityForm) -> Result<Community, Error>;
129 impl Community_ for Community {
130 fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error> {
131 use lemmy_db_schema::schema::community::dsl::*;
133 .filter(local.eq(true))
134 .filter(name.eq(community_name))
140 community_id: CommunityId,
142 ) -> Result<Community, Error> {
143 use lemmy_db_schema::schema::community::dsl::*;
144 diesel::update(community.find(community_id))
145 .set((deleted.eq(new_deleted), updated.eq(naive_now())))
146 .get_result::<Self>(conn)
151 community_id: CommunityId,
153 ) -> Result<Community, Error> {
154 use lemmy_db_schema::schema::community::dsl::*;
155 diesel::update(community.find(community_id))
156 .set((removed.eq(new_removed), updated.eq(naive_now())))
157 .get_result::<Self>(conn)
160 fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error> {
161 use lemmy_db_schema::schema::community::dsl::*;
162 community.select(actor_id).distinct().load::<String>(conn)
165 fn read_from_followers_url(
167 followers_url_: &DbUrl,
168 ) -> Result<Community, Error> {
169 use lemmy_db_schema::schema::community::dsl::*;
171 .filter(followers_url.eq(followers_url_))
175 fn upsert(conn: &PgConnection, community_form: &CommunityForm) -> Result<Community, Error> {
176 use lemmy_db_schema::schema::community::dsl::*;
177 insert_into(community)
178 .values(community_form)
179 .on_conflict(actor_id)
182 .get_result::<Self>(conn)
186 impl Joinable for CommunityModerator {
187 type Form = CommunityModeratorForm;
190 community_moderator_form: &CommunityModeratorForm,
191 ) -> Result<Self, Error> {
192 use lemmy_db_schema::schema::community_moderator::dsl::*;
193 insert_into(community_moderator)
194 .values(community_moderator_form)
195 .get_result::<Self>(conn)
200 community_moderator_form: &CommunityModeratorForm,
201 ) -> Result<usize, Error> {
202 use lemmy_db_schema::schema::community_moderator::dsl::*;
205 .filter(community_id.eq(community_moderator_form.community_id))
206 .filter(person_id.eq(community_moderator_form.person_id)),
212 impl DeleteableOrRemoveable for CommunitySafe {
213 fn blank_out_deleted_or_removed_info(mut self) -> Self {
214 self.title = "".into();
215 self.description = None;
222 impl DeleteableOrRemoveable for Community {
223 fn blank_out_deleted_or_removed_info(mut self) -> Self {
224 self.title = "".into();
225 self.description = None;
232 pub trait CommunityModerator_ {
233 fn delete_for_community(
235 for_community_id: CommunityId,
236 ) -> Result<usize, Error>;
237 fn get_person_moderated_communities(
239 for_person_id: PersonId,
240 ) -> Result<Vec<CommunityId>, Error>;
243 impl CommunityModerator_ for CommunityModerator {
244 fn delete_for_community(
246 for_community_id: CommunityId,
247 ) -> Result<usize, Error> {
248 use lemmy_db_schema::schema::community_moderator::dsl::*;
249 diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
252 fn get_person_moderated_communities(
254 for_person_id: PersonId,
255 ) -> Result<Vec<CommunityId>, Error> {
256 use lemmy_db_schema::schema::community_moderator::dsl::*;
258 .filter(person_id.eq(for_person_id))
259 .select(community_id)
260 .load::<CommunityId>(conn)
264 impl Bannable for CommunityPersonBan {
265 type Form = CommunityPersonBanForm;
268 community_person_ban_form: &CommunityPersonBanForm,
269 ) -> Result<Self, Error> {
270 use lemmy_db_schema::schema::community_person_ban::dsl::*;
271 insert_into(community_person_ban)
272 .values(community_person_ban_form)
273 .get_result::<Self>(conn)
278 community_person_ban_form: &CommunityPersonBanForm,
279 ) -> Result<usize, Error> {
280 use lemmy_db_schema::schema::community_person_ban::dsl::*;
283 .filter(community_id.eq(community_person_ban_form.community_id))
284 .filter(person_id.eq(community_person_ban_form.person_id)),
290 impl Followable for CommunityFollower {
291 type Form = CommunityFollowerForm;
294 community_follower_form: &CommunityFollowerForm,
295 ) -> Result<Self, Error> {
296 use lemmy_db_schema::schema::community_follower::dsl::*;
297 insert_into(community_follower)
298 .values(community_follower_form)
299 .on_conflict((community_id, person_id))
301 .set(community_follower_form)
302 .get_result::<Self>(conn)
306 community_id_: CommunityId,
307 person_id_: PersonId,
308 ) -> Result<Self, Error>
312 use lemmy_db_schema::schema::community_follower::dsl::*;
315 .filter(community_id.eq(community_id_))
316 .filter(person_id.eq(person_id_)),
318 .set(pending.eq(true))
319 .get_result::<Self>(conn)
323 community_follower_form: &CommunityFollowerForm,
324 ) -> Result<usize, Error> {
325 use lemmy_db_schema::schema::community_follower::dsl::*;
328 .filter(community_id.eq(&community_follower_form.community_id))
329 .filter(person_id.eq(&community_follower_form.person_id)),
333 // TODO: this function name only makes sense if you call it with a remote community. for a local
334 // community, it will also return true if only remote followers exist
335 fn has_local_followers(conn: &PgConnection, community_id_: CommunityId) -> Result<bool, Error> {
336 use lemmy_db_schema::schema::community_follower::dsl::*;
337 diesel::select(exists(
338 community_follower.filter(community_id.eq(community_id_)),
346 use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable};
347 use lemmy_db_schema::source::{community::*, person::*};
348 use serial_test::serial;
353 let conn = establish_unpooled_connection();
355 let new_person = PersonForm {
356 name: "bobbee".into(),
357 ..PersonForm::default()
360 let inserted_person = Person::create(&conn, &new_person).unwrap();
362 let new_community = CommunityForm {
364 title: "nada".to_owned(),
365 ..CommunityForm::default()
368 let inserted_community = Community::create(&conn, &new_community).unwrap();
370 let expected_community = Community {
371 id: inserted_community.id,
373 title: "nada".to_owned(),
378 published: inserted_community.published,
380 actor_id: inserted_community.actor_id.to_owned(),
384 last_refreshed_at: inserted_community.published,
387 followers_url: inserted_community.followers_url.to_owned(),
388 inbox_url: inserted_community.inbox_url.to_owned(),
389 shared_inbox_url: None,
392 let community_follower_form = CommunityFollowerForm {
393 community_id: inserted_community.id,
394 person_id: inserted_person.id,
398 let inserted_community_follower =
399 CommunityFollower::follow(&conn, &community_follower_form).unwrap();
401 let expected_community_follower = CommunityFollower {
402 id: inserted_community_follower.id,
403 community_id: inserted_community.id,
404 person_id: inserted_person.id,
405 pending: Some(false),
406 published: inserted_community_follower.published,
409 let community_moderator_form = CommunityModeratorForm {
410 community_id: inserted_community.id,
411 person_id: inserted_person.id,
414 let inserted_community_moderator =
415 CommunityModerator::join(&conn, &community_moderator_form).unwrap();
417 let expected_community_moderator = CommunityModerator {
418 id: inserted_community_moderator.id,
419 community_id: inserted_community.id,
420 person_id: inserted_person.id,
421 published: inserted_community_moderator.published,
424 let community_person_ban_form = CommunityPersonBanForm {
425 community_id: inserted_community.id,
426 person_id: inserted_person.id,
429 let inserted_community_person_ban =
430 CommunityPersonBan::ban(&conn, &community_person_ban_form).unwrap();
432 let expected_community_person_ban = CommunityPersonBan {
433 id: inserted_community_person_ban.id,
434 community_id: inserted_community.id,
435 person_id: inserted_person.id,
436 published: inserted_community_person_ban.published,
439 let read_community = Community::read(&conn, inserted_community.id).unwrap();
440 let updated_community =
441 Community::update(&conn, inserted_community.id, &new_community).unwrap();
442 let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap();
443 let left_community = CommunityModerator::leave(&conn, &community_moderator_form).unwrap();
444 let unban = CommunityPersonBan::unban(&conn, &community_person_ban_form).unwrap();
445 let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
446 Person::delete(&conn, inserted_person.id).unwrap();
448 assert_eq!(expected_community, read_community);
449 assert_eq!(expected_community, inserted_community);
450 assert_eq!(expected_community, updated_community);
451 assert_eq!(expected_community_follower, inserted_community_follower);
452 assert_eq!(expected_community_moderator, inserted_community_moderator);
453 assert_eq!(expected_community_person_ban, inserted_community_person_ban);
454 assert_eq!(1, ignored_community);
455 assert_eq!(1, left_community);
456 assert_eq!(1, unban);
457 // assert_eq!(2, loaded_count);
458 assert_eq!(1, num_deleted);