diff --git a/geneit_backend/src/controllers/families_controller.rs b/geneit_backend/src/controllers/families_controller.rs index f380f7d..95e1458 100644 --- a/geneit_backend/src/controllers/families_controller.rs +++ b/geneit_backend/src/controllers/families_controller.rs @@ -1,6 +1,7 @@ use crate::constants::{StaticConstraints, FAMILY_INVITATION_CODE_LEN}; use crate::controllers::HttpResult; use crate::extractors::family_extractor::{FamilyInPath, FamilyInPathWithAdminMembership}; +use crate::models::UserID; use crate::services::login_token_service::LoginToken; use crate::services::rate_limiter_service::RatedAction; use crate::services::{families_service, rate_limiter_service}; @@ -133,3 +134,38 @@ pub async fn renew_invitation_code(f: FamilyInPathWithAdminMembership) -> HttpRe pub async fn users(f: FamilyInPath) -> HttpResult { Ok(HttpResponse::Ok().json(families_service::get_memberships_of_family(f.family_id()).await?)) } + +#[derive(serde::Deserialize)] +pub struct UserIdInPath { + user_id: UserID, +} + +#[derive(serde::Deserialize)] +pub struct UpdateMembershipBody { + is_admin: bool, +} + +/// Update a membership +pub async fn update_membership( + f: FamilyInPathWithAdminMembership, + path: web::Path, + req: web::Json, +) -> HttpResult { + // An admin can not update his own membership + if path.user_id == f.user_id() { + return Ok(HttpResponse::Conflict().body("You cannot update your own membership!")); + } + + let mut membership = families_service::get_membership(f.family_id(), path.user_id).await?; + membership.is_admin = req.is_admin; + families_service::update_membership(&membership).await?; + + log::debug!( + "User {:?} updated the membership of user {:?} in the family {:?}", + f.user_id(), + path.user_id, + f.family_id() + ); + + Ok(HttpResponse::Accepted().finish()) +} diff --git a/geneit_backend/src/main.rs b/geneit_backend/src/main.rs index a0b27d1..23848ee 100644 --- a/geneit_backend/src/main.rs +++ b/geneit_backend/src/main.rs @@ -114,6 +114,10 @@ async fn main() -> std::io::Result<()> { "/family/{id}/users", web::get().to(families_controller::users), ) + .route( + "/family/{id}/user/{user_id}", + web::patch().to(families_controller::update_membership), + ) }) .bind(AppConfig::get().listen_address.as_str())? .run() diff --git a/geneit_backend/src/models.rs b/geneit_backend/src/models.rs index 4c24ead..1041c43 100644 --- a/geneit_backend/src/models.rs +++ b/geneit_backend/src/models.rs @@ -2,7 +2,7 @@ use crate::schema::{families, memberships, users}; use diesel::prelude::*; /// User ID holder -#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, PartialEq, Eq)] pub struct UserID(pub i32); #[derive(Queryable, Debug, serde::Serialize)] diff --git a/geneit_backend/src/services/families_service.rs b/geneit_backend/src/services/families_service.rs index 2a00354..85bc6bc 100644 --- a/geneit_backend/src/services/families_service.rs +++ b/geneit_backend/src/services/families_service.rs @@ -107,6 +107,23 @@ pub async fn get_membership(family_id: FamilyID, user_id: UserID) -> anyhow::Res }) } +/// Update a membership to a family +pub async fn update_membership(membership: &Membership) -> anyhow::Result<()> { + db_connection::execute(|conn| { + diesel::update( + memberships::dsl::memberships.filter( + memberships::dsl::user_id + .eq(membership.user_id().0) + .and(memberships::dsl::family_id.eq(membership.family_id().0)), + ), + ) + .set(memberships::dsl::is_admin.eq(membership.is_admin)) + .execute(conn) + })?; + + Ok(()) +} + #[derive(serde::Serialize)] pub struct FamilyMember { #[serde(flatten)]