Skip to content

Commit 07c054e

Browse files
committed
add delete handling for saved prompts
Signed-off-by: Jordan Dubrick <jdubrick@redhat.com>
1 parent 1c48724 commit 07c054e

2 files changed

Lines changed: 91 additions & 0 deletions

File tree

src/utils/saved_prompts.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ def list_saved_prompts_by_user(user_id: str) -> list[SavedPrompt]:
184184
185185
Returns:
186186
List of ``SavedPrompt`` rows for the user. Empty list if none exist.
187+
Tie order when ``created_at`` values are equal is database-defined.
187188
"""
188189
with get_session() as session:
189190
return (
@@ -192,3 +193,42 @@ def list_saved_prompts_by_user(user_id: str) -> list[SavedPrompt]:
192193
.order_by(SavedPrompt.created_at.desc())
193194
.all()
194195
)
196+
197+
198+
def delete_saved_prompt_by_id_and_user(prompt_id: str, user_id: str) -> None:
199+
"""Delete a saved prompt only if it belongs to the given user.
200+
201+
Parameters:
202+
prompt_id: Primary key of the saved prompt.
203+
user_id: Authenticated user attempting the delete.
204+
205+
Raises:
206+
SavedPromptNotFoundError: If no row exists for ``prompt_id``.
207+
SavedPromptAccessDeniedError: If the row exists but ``user_id`` does not
208+
match the owner.
209+
"""
210+
with get_session() as session:
211+
saved_prompt = session.query(SavedPrompt).filter_by(id=prompt_id).first()
212+
if saved_prompt is None:
213+
logger.debug(
214+
"Saved prompt not found for delete prompt_id=%s user_id=%s",
215+
prompt_id,
216+
user_id,
217+
)
218+
raise SavedPromptNotFoundError("Saved prompt not found")
219+
220+
if saved_prompt.user_id != user_id:
221+
logger.debug(
222+
"Saved prompt access denied for delete prompt_id=%s user_id=%s",
223+
prompt_id,
224+
user_id,
225+
)
226+
raise SavedPromptAccessDeniedError("Saved prompt access denied")
227+
228+
session.delete(saved_prompt)
229+
session.commit()
230+
logger.debug(
231+
"Deleted saved prompt id=%s for user_id=%s",
232+
prompt_id,
233+
user_id,
234+
)

tests/unit/utils/test_saved_prompts.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
from models.database.base import Base
1414
from models.database.saved_prompts import SavedPrompt
1515
from utils.saved_prompts import (
16+
SavedPromptAccessDeniedError,
1617
SavedPromptConflictError,
1718
SavedPromptLimitExceededError,
19+
SavedPromptNotFoundError,
1820
SavedPromptValidationError,
1921
create_saved_prompt,
22+
delete_saved_prompt_by_id_and_user,
2023
list_saved_prompts_by_user,
2124
validate_saved_prompt_content,
2225
validate_saved_prompt_name,
@@ -334,3 +337,51 @@ def test_list_returns_only_that_users_prompts_ordered_by_created_at_desc(
334337

335338
assert [p.id for p in results] == [newer.id, older.id]
336339
assert all(p.user_id == "user-1" for p in results)
340+
341+
342+
class TestDeleteSavedPromptByIdAndUser:
343+
"""Test cases for delete_saved_prompt_by_id_and_user."""
344+
345+
def test_delete_owned_prompt(
346+
self, patch_saved_prompts_get_session: None, sqlite_engine: Engine
347+
) -> None:
348+
"""Test deleting an owned prompt removes the row."""
349+
created = create_saved_prompt(
350+
"user-1", "to-delete", "body", max_prompts_per_user=50
351+
)
352+
353+
delete_saved_prompt_by_id_and_user(created.id, "user-1")
354+
355+
session_factory = sessionmaker(
356+
autocommit=False, autoflush=False, bind=sqlite_engine
357+
)
358+
with session_factory() as session:
359+
assert session.get(SavedPrompt, created.id) is None
360+
361+
def test_delete_missing_raises_not_found(
362+
self, patch_saved_prompts_get_session: None
363+
) -> None:
364+
"""Test deleting an unknown id raises SavedPromptNotFoundError."""
365+
with pytest.raises(SavedPromptNotFoundError) as exc_info:
366+
delete_saved_prompt_by_id_and_user("missing-id", "user-1")
367+
368+
assert str(exc_info.value) == "Saved prompt not found"
369+
370+
def test_delete_other_users_prompt_raises_access_denied(
371+
self, patch_saved_prompts_get_session: None, sqlite_engine: Engine
372+
) -> None:
373+
"""Test delete by non-owner raises access denied and leaves the row."""
374+
created = create_saved_prompt(
375+
"owner", "private", "body", max_prompts_per_user=50
376+
)
377+
378+
with pytest.raises(SavedPromptAccessDeniedError) as exc_info:
379+
delete_saved_prompt_by_id_and_user(created.id, "intruder")
380+
381+
assert str(exc_info.value) == "Saved prompt access denied"
382+
383+
session_factory = sessionmaker(
384+
autocommit=False, autoflush=False, bind=sqlite_engine
385+
)
386+
with session_factory() as session:
387+
assert session.get(SavedPrompt, created.id) is not None

0 commit comments

Comments
 (0)