Files
herbapi/herbapi-api/src/api/suppliers.rs
T
florian.berthold 484979ad53 Initial HerbAPI implementation
Rust/Axum REST API (herbapi-api) with PostgreSQL, S3/Garage, OIDC auth.
Dioxus 0.7 WASM frontend (herbapi-ui) with sidebar layout and botanical reference style.
9 SQL migrations covering families, species, cultivars, suppliers, companions, images, users, API tokens.
2026-03-14 00:02:29 +01:00

97 lines
2.8 KiB
Rust

use axum::extract::{Path, State};
use axum::Json;
use crate::auth::AuthUser;
use crate::db::{suppliers as db, models::*};
use crate::error::{AppError, Result};
use crate::state::AppState;
pub async fn list(State(state): State<AppState>) -> Result<Json<Vec<Supplier>>> {
let suppliers = db::list(&state.pool).await?;
Ok(Json(suppliers))
}
pub async fn get_by_slug(
State(state): State<AppState>,
Path(slug): Path<String>,
) -> Result<Json<Supplier>> {
let supplier = db::get_by_slug(&state.pool, &slug).await?;
Ok(Json(supplier))
}
pub async fn create(
State(state): State<AppState>,
auth: AuthUser,
Json(req): Json<CreateSupplier>,
) -> Result<Json<Supplier>> {
if !auth.can_write() {
return Err(AppError::Forbidden);
}
let supplier = db::create(&state.pool, &req).await?;
Ok(Json(supplier))
}
pub async fn update(
State(state): State<AppState>,
auth: AuthUser,
Path(r): Path<String>,
Json(req): Json<CreateSupplier>,
) -> Result<Json<Supplier>> {
if !auth.can_write() {
return Err(AppError::Forbidden);
}
let id: uuid::Uuid = r.parse().map_err(|_| AppError::NotFound("invalid id".into()))?;
let supplier = db::update(&state.pool, id, &req).await?;
Ok(Json(supplier))
}
pub async fn remove(
State(state): State<AppState>,
auth: AuthUser,
Path(r): Path<String>,
) -> Result<Json<serde_json::Value>> {
if !auth.is_admin() {
return Err(AppError::Forbidden);
}
let id: uuid::Uuid = r.parse().map_err(|_| AppError::NotFound("invalid id".into()))?;
db::delete(&state.pool, id).await?;
Ok(Json(serde_json::json!({ "deleted": true })))
}
// Cultivar-supplier links
pub async fn list_for_cultivar(
State(state): State<AppState>,
Path(r): Path<String>,
) -> Result<Json<Vec<CultivarSupplier>>> {
let id: uuid::Uuid = r.parse().map_err(|_| AppError::NotFound("invalid id".into()))?;
let links = db::list_for_cultivar(&state.pool, id).await?;
Ok(Json(links))
}
pub async fn link_cultivar(
State(state): State<AppState>,
auth: AuthUser,
Path(r): Path<String>,
Json(req): Json<CreateCultivarSupplier>,
) -> Result<Json<CultivarSupplier>> {
if !auth.can_write() {
return Err(AppError::Forbidden);
}
let id: uuid::Uuid = r.parse().map_err(|_| AppError::NotFound("invalid id".into()))?;
let link = db::link_cultivar(&state.pool, id, &req).await?;
Ok(Json(link))
}
pub async fn unlink_cultivar(
State(state): State<AppState>,
auth: AuthUser,
Path((cid, sid)): Path<(uuid::Uuid, uuid::Uuid)>,
) -> Result<Json<serde_json::Value>> {
if !auth.can_write() {
return Err(AppError::Forbidden);
}
db::unlink_cultivar(&state.pool, cid, sid).await?;
Ok(Json(serde_json::json!({ "deleted": true })))
}