diff --git a/astroplant-api/src/bin/astroplant-api.rs b/astroplant-api/src/bin/astroplant-api.rs index 51ac4ab..1979a9f 100644 --- a/astroplant-api/src/bin/astroplant-api.rs +++ b/astroplant-api/src/bin/astroplant-api.rs @@ -64,6 +64,7 @@ async fn main() -> anyhow::Result<()> { .route("/kits/:kit_serial", get(kit::kit_by_serial)) .route("/kits/:kit_serial", patch(kit::patch_kit)) .route("/kits/:kit_serial", delete(kit::delete_kit)) + .route("/kits/:kit_serial/members", get(kit::get_members)) .route("/kits/:kit_serial/password", post(kit::reset_password)) .route( "/kits/:kit_serial/configurations", diff --git a/astroplant-api/src/controllers/kit/mod.rs b/astroplant-api/src/controllers/kit/mod.rs index de08477..379a06b 100644 --- a/astroplant-api/src/controllers/kit/mod.rs +++ b/astroplant-api/src/controllers/kit/mod.rs @@ -3,6 +3,7 @@ use axum::Extension; use serde::{Deserialize, Serialize}; use crate::database::PgPool; +use crate::models::{KitMembership, User}; use crate::problem::{self, Problem}; use crate::response::{Response, ResponseBuilder}; use crate::utils::deserialize_some; @@ -245,3 +246,45 @@ pub async fn delete_kit( }) .await } + +/// Handles the `GET /kits/{kitSerial}/members` route. +pub async fn get_members( + Extension(pg): Extension, + Path(kit_serial): Path, + user_id: Option, +) -> Result { + let (_, _, kit) = helpers::fut_kit_permission_or_forbidden( + pg.clone(), + user_id, + kit_serial, + crate::authorization::KitAction::View, + ) + .await?; + + let conn = pg.get().await?; + + let kit_id = kit.id; + let members: Vec<(User, KitMembership)> = conn + .interact_flatten_err(move |conn| { + use diesel::prelude::*; + use schema::kit_memberships; + use schema::users; + + users::table + .inner_join(kit_memberships::table) + .filter(kit_memberships::kit_id.eq(kit_id)) + .get_results(conn) + }) + .await?; + + let v: Vec<_> = members + .into_iter() + .map(|(user, membership)| { + views::KitMembership::from(membership) + .with_kit(views::Kit::from(kit.clone())) + .with_user(views::User::from(user)) + }) + .collect(); + + Ok(ResponseBuilder::ok().body(v)) +} diff --git a/astroplant-api/src/controllers/user/mod.rs b/astroplant-api/src/controllers/user/mod.rs index 46aefa3..3834a3a 100644 --- a/astroplant-api/src/controllers/user/mod.rs +++ b/astroplant-api/src/controllers/user/mod.rs @@ -101,20 +101,18 @@ pub async fn list_kit_memberships( ) .await?; - let username = user.username.clone(); + let user_id = user.get_id(); let conn = pg.get().await?; let kit_memberships = conn - .interact(move |conn| { - models::KitMembership::memberships_with_kit_of_user_id(conn, user.get_id()) - }) + .interact(move |conn| models::KitMembership::memberships_with_kit_of_user_id(conn, user_id)) .await??; - let v: Vec> = kit_memberships + let v: Vec> = kit_memberships .into_iter() .map(|(kit, membership)| { views::KitMembership::from(membership) .with_kit(views::Kit::from(kit)) - .with_user(username.clone()) + .with_user(views::User::from(user.clone())) }) .collect(); Ok(ResponseBuilder::ok().body(v)) diff --git a/openapi.yaml b/openapi.yaml index 810e277..56c5706 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -243,6 +243,34 @@ paths: $ref: "#/components/responses/ErrorRateLimit" '500': $ref: "#/components/responses/ErrorInternalServer" + "/kits/{kitSerial}/members": + get: + summary: Members of a specific kit. + operationId: getKitMembers + security: + - bearerAuth: [] + tags: + - kits + parameters: + - name: kitSerial + in: path + required: true + description: The serial of the kit to get the members of. + schema: + type: string + responses: + '200': + description: The kit's members. + content: + application/json: + schema: + $ref: "#/components/schemas/KitMembership" + '401': + $ref: "#/components/responses/ErrorUnauthorized" + '429': + $ref: "#/components/responses/ErrorRateLimit" + '500': + $ref: "#/components/responses/ErrorInternalServer" "/kits/{kitSerial}/aggregate-measurements": get: summary: Aggregate measurements made by a kit. @@ -1274,7 +1302,7 @@ components: type: integer format: int32 user: - type: string + $ref: "#/components/schemas/User" kit: $ref: "#/components/schemas/Kit" accessConfigure: