diff options
Diffstat (limited to 'server/lemmy_db/src/community.rs')
-rw-r--r-- | server/lemmy_db/src/community.rs | 375 |
1 files changed, 375 insertions, 0 deletions
diff --git a/server/lemmy_db/src/community.rs b/server/lemmy_db/src/community.rs new file mode 100644 index 00000000..60752080 --- /dev/null +++ b/server/lemmy_db/src/community.rs @@ -0,0 +1,375 @@ +use crate::{ + schema::{community, community_follower, community_moderator, community_user_ban}, + Bannable, + Crud, + Followable, + Joinable, +}; +use diesel::{dsl::*, result::Error, *}; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize, Deserialize)] +#[table_name = "community"] +pub struct Community { + pub id: i32, + pub name: String, + pub title: String, + pub description: Option<String>, + pub category_id: i32, + pub creator_id: i32, + pub removed: bool, + pub published: chrono::NaiveDateTime, + pub updated: Option<chrono::NaiveDateTime>, + pub deleted: bool, + pub nsfw: bool, + pub actor_id: String, + pub local: bool, + pub private_key: Option<String>, + pub public_key: Option<String>, + pub last_refreshed_at: chrono::NaiveDateTime, +} + +// TODO add better delete, remove, lock actions here. +#[derive(Insertable, AsChangeset, Clone, Serialize, Deserialize, Debug)] +#[table_name = "community"] +pub struct CommunityForm { + pub name: String, + pub title: String, + pub description: Option<String>, + pub category_id: i32, + pub creator_id: i32, + pub removed: Option<bool>, + pub published: Option<chrono::NaiveDateTime>, + pub updated: Option<chrono::NaiveDateTime>, + pub deleted: Option<bool>, + pub nsfw: bool, + pub actor_id: String, + pub local: bool, + pub private_key: Option<String>, + pub public_key: Option<String>, + pub last_refreshed_at: Option<chrono::NaiveDateTime>, +} + +impl Crud<CommunityForm> for Community { + fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> { + use crate::schema::community::dsl::*; + community.find(community_id).first::<Self>(conn) + } + + fn delete(conn: &PgConnection, community_id: i32) -> Result<usize, Error> { + use crate::schema::community::dsl::*; + diesel::delete(community.find(community_id)).execute(conn) + } + + fn create(conn: &PgConnection, new_community: &CommunityForm) -> Result<Self, Error> { + use crate::schema::community::dsl::*; + insert_into(community) + .values(new_community) + .get_result::<Self>(conn) + } + + fn update( + conn: &PgConnection, + community_id: i32, + new_community: &CommunityForm, + ) -> Result<Self, Error> { + use crate::schema::community::dsl::*; + diesel::update(community.find(community_id)) + .set(new_community) + .get_result::<Self>(conn) + } +} + +impl Community { + pub fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Self, Error> { + use crate::schema::community::dsl::*; + community + .filter(name.eq(community_name)) + .first::<Self>(conn) + } + + pub fn read_from_actor_id(conn: &PgConnection, community_id: &str) -> Result<Self, Error> { + use crate::schema::community::dsl::*; + community + .filter(actor_id.eq(community_id)) + .first::<Self>(conn) + } + + pub fn list_local(conn: &PgConnection) -> Result<Vec<Self>, Error> { + use crate::schema::community::dsl::*; + community.filter(local.eq(true)).load::<Community>(conn) + } +} + +#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] +#[belongs_to(Community)] +#[table_name = "community_moderator"] +pub struct CommunityModerator { + pub id: i32, + pub community_id: i32, + pub user_id: i32, + pub published: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset, Clone)] +#[table_name = "community_moderator"] +pub struct CommunityModeratorForm { + pub community_id: i32, + pub user_id: i32, +} + +impl Joinable<CommunityModeratorForm> for CommunityModerator { + fn join( + conn: &PgConnection, + community_user_form: &CommunityModeratorForm, + ) -> Result<Self, Error> { + use crate::schema::community_moderator::dsl::*; + insert_into(community_moderator) + .values(community_user_form) + .get_result::<Self>(conn) + } + + fn leave( + conn: &PgConnection, + community_user_form: &CommunityModeratorForm, + ) -> Result<usize, Error> { + use crate::schema::community_moderator::dsl::*; + diesel::delete( + community_moderator + .filter(community_id.eq(community_user_form.community_id)) + .filter(user_id.eq(community_user_form.user_id)), + ) + .execute(conn) + } +} + +impl CommunityModerator { + pub fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error> { + use crate::schema::community_moderator::dsl::*; + diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn) + } +} + +#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] +#[belongs_to(Community)] +#[table_name = "community_user_ban"] +pub struct CommunityUserBan { + pub id: i32, + pub community_id: i32, + pub user_id: i32, + pub published: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset, Clone)] +#[table_name = "community_user_ban"] +pub struct CommunityUserBanForm { + pub community_id: i32, + pub user_id: i32, +} + +impl Bannable<CommunityUserBanForm> for CommunityUserBan { + fn ban( + conn: &PgConnection, + community_user_ban_form: &CommunityUserBanForm, + ) -> Result<Self, Error> { + use crate::schema::community_user_ban::dsl::*; + insert_into(community_user_ban) + .values(community_user_ban_form) + .get_result::<Self>(conn) + } + + fn unban( + conn: &PgConnection, + community_user_ban_form: &CommunityUserBanForm, + ) -> Result<usize, Error> { + use crate::schema::community_user_ban::dsl::*; + diesel::delete( + community_user_ban + .filter(community_id.eq(community_user_ban_form.community_id)) + .filter(user_id.eq(community_user_ban_form.user_id)), + ) + .execute(conn) + } +} + +#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)] +#[belongs_to(Community)] +#[table_name = "community_follower"] +pub struct CommunityFollower { + pub id: i32, + pub community_id: i32, + pub user_id: i32, + pub published: chrono::NaiveDateTime, +} + +#[derive(Insertable, AsChangeset, Clone)] +#[table_name = "community_follower"] +pub struct CommunityFollowerForm { + pub community_id: i32, + pub user_id: i32, +} + +impl Followable<CommunityFollowerForm> for CommunityFollower { + fn follow( + conn: &PgConnection, + community_follower_form: &CommunityFollowerForm, + ) -> Result<Self, Error> { + use crate::schema::community_follower::dsl::*; + insert_into(community_follower) + .values(community_follower_form) + .get_result::<Self>(conn) + } + fn unfollow( + conn: &PgConnection, + community_follower_form: &CommunityFollowerForm, + ) -> Result<usize, Error> { + use crate::schema::community_follower::dsl::*; + diesel::delete( + community_follower + .filter(community_id.eq(&community_follower_form.community_id)) + .filter(user_id.eq(&community_follower_form.user_id)), + ) + .execute(conn) + } +} + +#[cfg(test)] +mod tests { + use crate::{community::*, tests::establish_unpooled_connection, user::*, ListingType, SortType}; + + #[test] + fn test_crud() { + let conn = establish_unpooled_connection(); + + let new_user = UserForm { + name: "bobbee".into(), + preferred_username: None, + password_encrypted: "nope".into(), + email: None, + matrix_user_id: None, + avatar: None, + admin: false, + banned: false, + updated: None, + show_nsfw: false, + theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, + lang: "browser".into(), + show_avatars: true, + send_notifications_to_email: false, + actor_id: "http://fake.com".into(), + bio: None, + local: true, + private_key: None, + public_key: None, + last_refreshed_at: None, + }; + + let inserted_user = User_::create(&conn, &new_user).unwrap(); + + let new_community = CommunityForm { + name: "TIL".into(), + creator_id: inserted_user.id, + title: "nada".to_owned(), + description: None, + category_id: 1, + nsfw: false, + removed: None, + deleted: None, + updated: None, + actor_id: "http://fake.com".into(), + local: true, + private_key: None, + public_key: None, + last_refreshed_at: None, + published: None, + }; + + let inserted_community = Community::create(&conn, &new_community).unwrap(); + + let expected_community = Community { + id: inserted_community.id, + creator_id: inserted_user.id, + name: "TIL".into(), + title: "nada".to_owned(), + description: None, + category_id: 1, + nsfw: false, + removed: false, + deleted: false, + published: inserted_community.published, + updated: None, + actor_id: "http://fake.com".into(), + local: true, + private_key: None, + public_key: None, + last_refreshed_at: inserted_community.published, + }; + + let community_follower_form = CommunityFollowerForm { + community_id: inserted_community.id, + user_id: inserted_user.id, + }; + + let inserted_community_follower = + CommunityFollower::follow(&conn, &community_follower_form).unwrap(); + + let expected_community_follower = CommunityFollower { + id: inserted_community_follower.id, + community_id: inserted_community.id, + user_id: inserted_user.id, + published: inserted_community_follower.published, + }; + + let community_user_form = CommunityModeratorForm { + community_id: inserted_community.id, + user_id: inserted_user.id, + }; + + let inserted_community_user = CommunityModerator::join(&conn, &community_user_form).unwrap(); + + let expected_community_user = CommunityModerator { + id: inserted_community_user.id, + community_id: inserted_community.id, + user_id: inserted_user.id, + published: inserted_community_user.published, + }; + + let community_user_ban_form = CommunityUserBanForm { + community_id: inserted_community.id, + user_id: inserted_user.id, + }; + + let inserted_community_user_ban = + CommunityUserBan::ban(&conn, &community_user_ban_form).unwrap(); + + let expected_community_user_ban = CommunityUserBan { + id: inserted_community_user_ban.id, + community_id: inserted_community.id, + user_id: inserted_user.id, + published: inserted_community_user_ban.published, + }; + + let read_community = Community::read(&conn, inserted_community.id).unwrap(); + let updated_community = + Community::update(&conn, inserted_community.id, &new_community).unwrap(); + let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap(); + let left_community = CommunityModerator::leave(&conn, &community_user_form).unwrap(); + let unban = CommunityUserBan::unban(&conn, &community_user_ban_form).unwrap(); + let num_deleted = Community::delete(&conn, inserted_community.id).unwrap(); + User_::delete(&conn, inserted_user.id).unwrap(); + + assert_eq!(expected_community, read_community); + assert_eq!(expected_community, inserted_community); + assert_eq!(expected_community, updated_community); + assert_eq!(expected_community_follower, inserted_community_follower); + assert_eq!(expected_community_user, inserted_community_user); + assert_eq!(expected_community_user_ban, inserted_community_user_ban); + assert_eq!(1, ignored_community); + assert_eq!(1, left_community); + assert_eq!(1, unban); + // assert_eq!(2, loaded_count); + assert_eq!(1, num_deleted); + } +} |