use axum::{ extract::{State, Path}, http::StatusCode, Json, }; use axum_login::AuthSession; use sea_orm::DatabaseConnection; use serde::Serialize; use utoipa::ToSchema; use crate::auth::AuthBackend; use crate::services::{UserService, FamilyService}; #[derive(Debug, Serialize, ToSchema)] pub struct LeaveFamilyResponse { pub family_deleted: bool, } #[derive(Debug, Serialize, ToSchema)] pub struct FamilyMember { pub id: i32, pub username: Option, pub email: Option, pub is_admin: bool, } #[utoipa::path( post, path = "/me/leave-family", tag = "user", responses( (status = 200, description = "Left family successfully", body = LeaveFamilyResponse), (status = 400, description = "User is not in a family"), (status = 401, description = "Not authenticated") ) )] pub async fn leave_family( auth_session: AuthSession, State(db): State, ) -> Result, StatusCode> { let user = auth_session.user.ok_or(StatusCode::UNAUTHORIZED)?; let result = UserService::leave_family(&db, user.id) .await .map_err(|e| { if e.to_string().contains("not in a family") { StatusCode::BAD_REQUEST } else { StatusCode::INTERNAL_SERVER_ERROR } })?; Ok(Json(LeaveFamilyResponse { family_deleted: result.family_deleted, })) } #[utoipa::path( get, path = "/families/{family_id}/members", tag = "families", params( ("family_id" = i32, Path, description = "Family ID") ), responses( (status = 200, description = "List of family members", body = Vec), (status = 401, description = "Not authenticated"), (status = 403, description = "Access denied") ) )] pub async fn get_family_members( auth_session: AuthSession, State(db): State, Path(family_id): Path, ) -> Result>, StatusCode> { let user = auth_session.user.ok_or(StatusCode::UNAUTHORIZED)?; if user.family_id != Some(family_id) && !user.is_admin { return Err(StatusCode::FORBIDDEN); } let members = FamilyService::get_members(&db, family_id) .await .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; let response: Vec = members .into_iter() .map(|m| FamilyMember { id: m.id, username: m.username, email: m.email, is_admin: m.is_admin, }) .collect(); Ok(Json(response)) }