use crate::connections::db_connection; use crate::constants::FAMILY_INVITATION_CODE_LEN; use crate::models::{Family, FamilyID, Membership, NewFamily, NewMembership, UserID}; use crate::schema::{families, memberships}; use crate::utils::string_utils::rand_str; use crate::utils::time_utils::time; use diesel::prelude::*; /// Create a new family, with an initial administrator pub async fn create(name: &str, user_id: UserID) -> anyhow::Result { let family = db_connection::execute(|conn| { let res: Family = diesel::insert_into(families::table) .values(&NewFamily { name: name.trim(), invitation_code: rand_str(FAMILY_INVITATION_CODE_LEN), time_create: time() as i64, }) .get_result(conn)?; Ok(res) })?; add_member(family.id(), user_id, true).await?; Ok(family) } /// Add a member to a family pub async fn add_member( family_id: FamilyID, user_id: UserID, admin: bool, ) -> anyhow::Result { db_connection::execute(|conn| { let res = diesel::insert_into(memberships::table) .values(&NewMembership { user_id: user_id.0, family_id: family_id.0, time_create: time() as i64, is_admin: admin, }) .get_result(conn)?; Ok(res) }) } /// Find a family by invitation code pub async fn get_by_invitation_code(code: &str) -> anyhow::Result { db_connection::execute(|conn| { families::table .filter(families::dsl::invitation_code.eq(code)) .first(conn) }) } /// Check if a given user is member of a family or not pub async fn is_member(family_id: FamilyID, user_id: UserID) -> anyhow::Result { db_connection::execute(|conn| { memberships::table .filter(memberships::dsl::family_id.eq(family_id.0)) .filter(memberships::dsl::user_id.eq(user_id.0)) .count() .get_result(conn) }) .map(|c: i64| c > 0) } /// Remove a membership to a family pub async fn remove_membership(_family_id: FamilyID, _user_id: UserID) { todo!() } /// Remove all memberships of user pub async fn remove_all_user_membership(_user_id: UserID) -> anyhow::Result<()> { todo!() }