create routes for body parts and muscles

This commit is contained in:
2024-12-11 00:13:52 -08:00
parent 726092e31b
commit 47c37e375d
9 changed files with 129 additions and 22 deletions

View File

@@ -6,7 +6,7 @@ use utoipa_axum::{router::OpenApiRouter, routes};
use utoipa_swagger_ui::SwaggerUi;
// tags
use v1::auth::AUTH_TAG;
use v1::{auth::AUTH_TAG, body_parts::BODY_PARTS_TAG, exercises::EXERCISES_TAG};
mod v1;
mod structs;
@@ -27,6 +27,8 @@ pub(crate) use utoipa::ToSchema;
#[openapi(
tags(
(name = AUTH_TAG, description = "Authentication API endpoints"),
(name = EXERCISES_TAG, description = "Exercise API endpoints"),
(name = BODY_PARTS_TAG, description = "Body part API endpoints"),
// (name = CUSTOMER_TAG, description = "Customer API endpoints"),
// (name = ORDER_TAG, description = "Order API endpoints")
),
@@ -71,8 +73,7 @@ async fn main() -> anyhow::Result<()> {
.routes(routes!(health_check))
.routes(routes!(index))
.with_state(state.clone())
.nest("/api/v1/auth", v1::auth::router(state.clone()))
.nest("/api/v1/exercises", v1::exercises::router(state.clone()))
.nest("/api/v1", v1::router(state.clone()))
.split_for_parts();
let router = router.merge(SwaggerUi::new("/docs").url("/docs/openapi.json", api));

View File

@@ -7,7 +7,7 @@ pub mod login;
pub const AUTH_TAG: &str = "auth";
pub fn router(state: AppState) -> OpenApiRouter {
pub(super) fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.routes(routes!(signup::signup))
.routes(routes!(login::login))

View File

@@ -0,0 +1,34 @@
use extractors::users::UserId;
use sqlx::query;
use crate::*;
#[derive(Serialize, Deserialize, ToSchema)]
pub struct CreateBodyPartBody {
name: String,
}
#[utoipa::path(post, path = "/create", responses((status = OK, body = String)), tag = super::BODY_PARTS_TAG)]
pub async fn create(
State(state): State<AppState>,
UserId(user_id): UserId,
Json(body): Json<CreateBodyPartBody>,
) -> Result<String, AppError> {
let is_admin = query!("SELECT is_admin FROM users WHERE id = $1", user_id)
.fetch_one(&*state.db)
.await?
.is_admin;
if !is_admin {
return Err(AppError::Error(Errors::Unauthorized));
}
let out = query!(
"INSERT INTO body_parts (name) VALUES ($1) RETURNING id",
body.name
)
.fetch_one(&*state.db)
.await?;
Ok(out.id.to_string())
}

13
src/v1/body_parts/mod.rs Normal file
View File

@@ -0,0 +1,13 @@
use crate::AppState;
pub(super) use super::*;
pub mod create;
pub const BODY_PARTS_TAG: &str = "body_parts";
pub(super) fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.routes(routes!(create::create))
.with_state(state)
}

View File

@@ -1,6 +1,6 @@
use chrono::{DateTime, Utc};
use chrono::NaiveDateTime;
use extractors::users::UserId;
use sqlx::{query, query_as};
use sqlx::query;
use structs::exercise_types::ExerciseType;
use uuid::Uuid;
@@ -12,6 +12,9 @@ pub struct CreateExerciseBody {
// todo: make this an enum
exercise_type: ExerciseType,
description: String,
body_parts: Vec<String>,
primary_muscles: Vec<String>,
secondary_muscles: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone, sqlx::Type, PartialEq, sqlx::FromRow)]
@@ -22,7 +25,7 @@ pub struct Exercise {
pub description: String,
pub author_id: Uuid,
pub official: bool,
pub created_at: DateTime<Utc>,
pub created_at: NaiveDateTime,
}
#[utoipa::path(post, path = "/create", responses((status = OK, body = String)), tag = super::EXERCISES_TAG)]
@@ -36,24 +39,19 @@ pub async fn create(
.await?
.is_admin;
if !is_admin {
return Err(AppError::Error(Errors::Unauthorized));
}
// INSERT INTO users (id, created_at, updated_at, role) VALUES ($1, NOW(), NOW(), ($2::text)::user_role) RETURNING id, created_at, updated_at, role as "role:UserRole"
//
let insert = query_as!(
Exercise,
query!(
r#"
INSERT INTO exercises (name, exercise_type, description, author_id, official)
VALUES ($1, ($2::text)::exercise_type, $3, $4, $5)
RETURNING id, name, exercise_type, description, author_id, official, created_at
INSERT INTO exercises (name, exercise_type, official, author_id, description)
VALUES ($1, $2, $3, $4, $5)
"#,
body.name,
body.exercise_type.to_string(),
body.description,
body.exercise_type as ExerciseType,
is_admin,
user,
false
);
body.description
)
.fetch_one(&*state.db)
.await?;
todo!()
}

View File

@@ -6,7 +6,7 @@ pub mod create;
pub const EXERCISES_TAG: &str = "exercises";
pub fn router(state: AppState) -> OpenApiRouter {
pub(super) fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.routes(routes!(create::create))
.with_state(state)

View File

@@ -1,5 +1,18 @@
pub(super) use utoipa_axum::router::OpenApiRouter;
pub(super) use utoipa_axum::routes;
use crate::AppState;
pub mod auth;
pub mod body_parts;
pub mod exercises;
pub mod muscles;
pub fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.with_state(state.clone())
.nest("/auth", auth::router(state.clone()))
.nest("/exercises", exercises::router(state.clone()))
.nest("/body_parts", body_parts::router(state.clone()))
.nest("/muscles", muscles::router(state.clone()))
}

35
src/v1/muscles/create.rs Normal file
View File

@@ -0,0 +1,35 @@
use extractors::users::UserId;
use sqlx::query;
use crate::*;
#[derive(Serialize, Deserialize, ToSchema)]
pub struct CreateMuscleBody {
name: String,
body_parts: Vec<String>,
}
#[utoipa::path(post, path = "/create", responses((status = OK, body = String)), tag = super::MUSCLES_TAG)]
pub async fn create(
State(state): State<AppState>,
UserId(user_id): UserId,
Json(body): Json<CreateMuscleBody>,
) -> Result<String, AppError> {
let is_admin = query!("SELECT is_admin FROM users WHERE id = $1", user_id)
.fetch_one(&*state.db)
.await?
.is_admin;
if !is_admin {
return Err(AppError::Error(Errors::Unauthorized));
}
let out = query!(
"INSERT INTO muscles (name) VALUES ($1) RETURNING id",
body.name
)
.fetch_one(&*state.db)
.await?;
Ok(out.id.to_string())
}

13
src/v1/muscles/mod.rs Normal file
View File

@@ -0,0 +1,13 @@
use crate::AppState;
pub(super) use super::*;
pub mod create;
pub const MUSCLES_TAG: &str = "muscles";
pub(super) fn router(state: AppState) -> OpenApiRouter {
OpenApiRouter::new()
.routes(routes!(create::create))
.with_state(state)
}