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.
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
use sqlx::PgPool;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::{AppError, Result};
|
||||
use super::models::Image;
|
||||
|
||||
pub async fn list_for_entity(pool: &PgPool, entity_type: &str, entity_id: Uuid) -> Result<Vec<Image>> {
|
||||
sqlx::query_as::<_, Image>(
|
||||
"SELECT * FROM images WHERE entity_type = $1 AND entity_id = $2 ORDER BY is_primary DESC, created_at"
|
||||
)
|
||||
.bind(entity_type).bind(entity_id)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub async fn create(
|
||||
pool: &PgPool,
|
||||
entity_type: &str,
|
||||
entity_id: Uuid,
|
||||
s3_key: &str,
|
||||
caption: Option<&str>,
|
||||
source_url: Option<&str>,
|
||||
license: Option<&str>,
|
||||
is_primary: bool,
|
||||
) -> Result<Image> {
|
||||
let id = Uuid::now_v7();
|
||||
sqlx::query_as::<_, Image>(
|
||||
"INSERT INTO images (id, entity_type, entity_id, s3_key, caption, source_url, license, is_primary)
|
||||
VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *"
|
||||
)
|
||||
.bind(id).bind(entity_type).bind(entity_id).bind(s3_key)
|
||||
.bind(caption).bind(source_url).bind(license).bind(is_primary)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
pub async fn delete(pool: &PgPool, id: Uuid) -> Result<Image> {
|
||||
sqlx::query_as::<_, Image>("DELETE FROM images WHERE id = $1 RETURNING *")
|
||||
.bind(id)
|
||||
.fetch_optional(pool)
|
||||
.await?
|
||||
.ok_or_else(|| AppError::NotFound(format!("Image not found: {id}")))
|
||||
}
|
||||
Reference in New Issue
Block a user