add the ability to make props non-droppable

This commit is contained in:
Evan Carroll 2026-01-13 17:46:56 -06:00
parent ea3b444d71
commit 845d64c981
5 changed files with 82 additions and 14 deletions

View file

@ -20,6 +20,7 @@ pub async fn list_user_inventory<'e>(
layer,
is_transferable,
is_portable,
is_droppable,
origin,
acquired_at
FROM props.inventory
@ -35,16 +36,30 @@ pub async fn list_user_inventory<'e>(
}
/// Drop a prop (remove from inventory).
/// Returns an error if the prop is non-droppable (essential prop).
pub async fn drop_inventory_item<'e>(
executor: impl PgExecutor<'e>,
user_id: Uuid,
item_id: Uuid,
) -> Result<(), AppError> {
let result = sqlx::query(
// Use a CTE to check existence/droppability and delete in a single query
// Returns: (existed, was_droppable, was_deleted)
let result: Option<(bool, bool, bool)> = sqlx::query_as(
r#"
DELETE FROM props.inventory
WHERE id = $1 AND user_id = $2
RETURNING id
WITH item_info AS (
SELECT id, is_droppable
FROM props.inventory
WHERE id = $1 AND user_id = $2
),
deleted AS (
DELETE FROM props.inventory
WHERE id = $1 AND user_id = $2 AND is_droppable = true
RETURNING id
)
SELECT
EXISTS(SELECT 1 FROM item_info) AS existed,
COALESCE((SELECT is_droppable FROM item_info), false) AS was_droppable,
EXISTS(SELECT 1 FROM deleted) AS was_deleted
"#,
)
.bind(item_id)
@ -52,10 +67,26 @@ pub async fn drop_inventory_item<'e>(
.fetch_optional(executor)
.await?;
if result.is_none() {
return Err(AppError::NotFound(
"Inventory item not found or not owned by user".to_string(),
));
match result {
Some((false, _, _)) | None => {
return Err(AppError::NotFound(
"Inventory item not found or not owned by user".to_string(),
));
}
Some((true, false, _)) => {
return Err(AppError::Forbidden(
"This prop cannot be dropped - it is an essential prop".to_string(),
));
}
Some((true, true, true)) => {
// Successfully deleted
}
Some((true, true, false)) => {
// Should not happen - item existed, was droppable, but wasn't deleted
return Err(AppError::Internal(
"Unexpected error dropping inventory item".to_string(),
));
}
}
Ok(())