diff --git a/crates/api/src/community.rs b/crates/api/src/community.rs index 0ca4ac47a..18a4dc461 100644 --- a/crates/api/src/community.rs +++ b/crates/api/src/community.rs @@ -399,16 +399,14 @@ impl Perform for TransferCommunity { } // Mod tables - // TODO there should probably be another table for transfer community - // Right now, it will just look like it modded them twice - let form = ModAddCommunityForm { + let form = ModTransferCommunityForm { mod_person_id: local_user_view.person.id, other_person_id: data.person_id, community_id: data.community_id, removed: Some(false), }; blocking(context.pool(), move |conn| { - ModAddCommunity::create(conn, &form) + ModTransferCommunity::create(conn, &form) }) .await??; diff --git a/crates/api/src/site.rs b/crates/api/src/site.rs index d67c11815..7b6783a70 100644 --- a/crates/api/src/site.rs +++ b/crates/api/src/site.rs @@ -40,6 +40,7 @@ use lemmy_db_views_moderator::{ mod_remove_community_view::ModRemoveCommunityView, mod_remove_post_view::ModRemovePostView, mod_sticky_post_view::ModStickyPostView, + mod_transfer_community_view::ModTransferCommunityView, }; use lemmy_utils::{ location_info, @@ -97,6 +98,11 @@ impl Perform for GetModlog { }) .await??; + let transferred_to_community = blocking(context.pool(), move |conn| { + ModTransferCommunityView::list(conn, community_id, mod_person_id, page, limit) + }) + .await??; + // These arrays are only for the full modlog, when a community isn't given let (removed_communities, banned, added) = if data.community_id.is_none() { blocking(context.pool(), move |conn| { @@ -122,6 +128,7 @@ impl Perform for GetModlog { banned, added_to_community, added, + transferred_to_community, }) } } diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index e5c167f42..796549860 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -16,6 +16,7 @@ use lemmy_db_views_moderator::{ mod_remove_community_view::ModRemoveCommunityView, mod_remove_post_view::ModRemovePostView, mod_sticky_post_view::ModStickyPostView, + mod_transfer_community_view::ModTransferCommunityView, }; use serde::{Deserialize, Serialize}; @@ -60,6 +61,7 @@ pub struct GetModlogResponse { pub banned_from_community: Vec, pub banned: Vec, pub added_to_community: Vec, + pub transferred_to_community: Vec, pub added: Vec, } diff --git a/crates/db_queries/src/source/moderator.rs b/crates/db_queries/src/source/moderator.rs index 25ef1416d..eee5d5e9f 100644 --- a/crates/db_queries/src/source/moderator.rs +++ b/crates/db_queries/src/source/moderator.rs @@ -192,6 +192,33 @@ impl Crud for ModAddCommunity { } } +impl Crud for ModTransferCommunity { + type Form = ModTransferCommunityForm; + type IdType = i32; + fn read(conn: &PgConnection, from_id: i32) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + mod_transfer_community.find(from_id).first::(conn) + } + + fn create(conn: &PgConnection, form: &ModTransferCommunityForm) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + insert_into(mod_transfer_community) + .values(form) + .get_result::(conn) + } + + fn update( + conn: &PgConnection, + from_id: i32, + form: &ModTransferCommunityForm, + ) -> Result { + use lemmy_db_schema::schema::mod_transfer_community::dsl::*; + diesel::update(mod_transfer_community.find(from_id)) + .set(form) + .get_result::(conn) + } +} + impl Crud for ModAdd { type Form = ModAddForm; type IdType = i32; diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 8c17b0bd5..ad1ce2b35 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -181,6 +181,17 @@ table! { } } +table! { + mod_transfer_community (id) { + id -> Int4, + mod_person_id -> Int4, + other_person_id -> Int4, + community_id -> Int4, + removed -> Nullable, + when_ -> Timestamp, + } +} + table! { mod_ban (id) { id -> Int4, @@ -549,6 +560,7 @@ joinable!(community_person_ban -> community (community_id)); joinable!(community_person_ban -> person (person_id)); joinable!(local_user -> person (person_id)); joinable!(mod_add_community -> community (community_id)); +joinable!(mod_transfer_community -> community (community_id)); joinable!(mod_ban_from_community -> community (community_id)); joinable!(mod_lock_post -> person (mod_person_id)); joinable!(mod_lock_post -> post (post_id)); @@ -593,6 +605,7 @@ allow_tables_to_appear_in_same_query!( local_user, mod_add, mod_add_community, + mod_transfer_community, mod_ban, mod_ban_from_community, mod_lock_post, diff --git a/crates/db_schema/src/source/moderator.rs b/crates/db_schema/src/source/moderator.rs index 19580fb92..66889ae50 100644 --- a/crates/db_schema/src/source/moderator.rs +++ b/crates/db_schema/src/source/moderator.rs @@ -9,6 +9,7 @@ use crate::{ mod_remove_community, mod_remove_post, mod_sticky_post, + mod_transfer_community, }, CommentId, CommunityId, @@ -181,6 +182,26 @@ pub struct ModAddCommunityForm { pub removed: Option, } +#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] +#[table_name = "mod_transfer_community"] +pub struct ModTransferCommunity { + pub id: i32, + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, + pub removed: Option, + pub when_: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset)] +#[table_name = "mod_transfer_community"] +pub struct ModTransferCommunityForm { + pub mod_person_id: PersonId, + pub other_person_id: PersonId, + pub community_id: CommunityId, + pub removed: Option, +} + #[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)] #[table_name = "mod_add"] pub struct ModAdd { diff --git a/crates/db_views_moderator/src/lib.rs b/crates/db_views_moderator/src/lib.rs index 827dd1447..354504c4a 100644 --- a/crates/db_views_moderator/src/lib.rs +++ b/crates/db_views_moderator/src/lib.rs @@ -7,3 +7,4 @@ pub mod mod_remove_comment_view; pub mod mod_remove_community_view; pub mod mod_remove_post_view; pub mod mod_sticky_post_view; +pub mod mod_transfer_community_view; diff --git a/crates/db_views_moderator/src/mod_transfer_community_view.rs b/crates/db_views_moderator/src/mod_transfer_community_view.rs new file mode 100644 index 000000000..94c0abc7d --- /dev/null +++ b/crates/db_views_moderator/src/mod_transfer_community_view.rs @@ -0,0 +1,85 @@ +use diesel::{result::Error, *}; +use lemmy_db_queries::{limit_and_offset, ToSafe, ViewToVec}; +use lemmy_db_schema::{ + schema::{community, mod_transfer_community, person, person_alias_1}, + source::{ + community::{Community, CommunitySafe}, + moderator::ModTransferCommunity, + person::{Person, PersonAlias1, PersonSafe, PersonSafeAlias1}, + }, + CommunityId, + PersonId, +}; +use serde::Serialize; + +#[derive(Debug, Serialize, Clone)] +pub struct ModTransferCommunityView { + pub mod_transfer_community: ModTransferCommunity, + pub moderator: PersonSafe, + pub community: CommunitySafe, + pub modded_person: PersonSafeAlias1, +} + +type ModTransferCommunityViewTuple = ( + ModTransferCommunity, + PersonSafe, + CommunitySafe, + PersonSafeAlias1, +); + +impl ModTransferCommunityView { + pub fn list( + conn: &PgConnection, + community_id: Option, + mod_person_id: Option, + page: Option, + limit: Option, + ) -> Result, Error> { + let mut query = mod_transfer_community::table + .inner_join(person::table.on(mod_transfer_community::mod_person_id.eq(person::id))) + .inner_join(community::table) + .inner_join( + person_alias_1::table.on(mod_transfer_community::other_person_id.eq(person_alias_1::id)), + ) + .select(( + mod_transfer_community::all_columns, + Person::safe_columns_tuple(), + Community::safe_columns_tuple(), + PersonAlias1::safe_columns_tuple(), + )) + .into_boxed(); + + if let Some(mod_person_id) = mod_person_id { + query = query.filter(mod_transfer_community::mod_person_id.eq(mod_person_id)); + }; + + if let Some(community_id) = community_id { + query = query.filter(mod_transfer_community::community_id.eq(community_id)); + }; + + let (limit, offset) = limit_and_offset(page, limit); + + let res = query + .limit(limit) + .offset(offset) + .order_by(mod_transfer_community::when_.desc()) + .load::(conn)?; + + Ok(Self::from_tuple_to_vec(res)) + } +} + +impl ViewToVec for ModTransferCommunityView { + type DbTuple = ModTransferCommunityViewTuple; + fn from_tuple_to_vec(items: Vec) -> Vec { + items + .iter() + .map(|a| Self { + mod_transfer_community: a.0.to_owned(), + moderator: a.1.to_owned(), + community: a.2.to_owned(), + modded_person: a.3.to_owned(), + }) + .collect::>() + } +} diff --git a/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql b/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql new file mode 100644 index 000000000..8a2d8820a --- /dev/null +++ b/migrations/2021-08-17-210508_create_mod_transfer_community/down.sql @@ -0,0 +1 @@ +drop table mod_transfer_community; diff --git a/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql b/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql new file mode 100644 index 000000000..b43cf1408 --- /dev/null +++ b/migrations/2021-08-17-210508_create_mod_transfer_community/up.sql @@ -0,0 +1,9 @@ +-- Add the mod_transfer_community log table +create table mod_transfer_community ( + id serial primary key, + mod_person_id int references person on update cascade on delete cascade not null, + other_person_id int references person on update cascade on delete cascade not null, + community_id int references community on update cascade on delete cascade not null, + removed boolean default false, + when_ timestamp not null default now() +);