Files
herbapi/herbapi-api/src/db/images.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

46 lines
1.4 KiB
Rust

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}")))
}