Files
office_translator/services/prompt_service.py
2026-03-07 11:42:58 +01:00

128 lines
3.7 KiB
Python

"""
Prompt Service for Translation
Story 3.12: Custom Prompts - Application lors Traduction LLM
Provides functions to retrieve prompt content and validate access.
"""
import uuid
import logging
from typing import Optional, Tuple
from database.connection import get_sync_session
from database.models import CustomPrompt
from utils.exceptions import PromptNotFoundError
logger = logging.getLogger(__name__)
def _validate_uuid(id_str: str, id_name: str = "ID") -> None:
"""
Validate that a string is a valid UUID.
Args:
id_str: String to validate
id_name: Name of the ID for error messages
Raises:
PromptNotFoundError: If the string is not a valid UUID
"""
try:
uuid.UUID(id_str)
except (ValueError, AttributeError):
raise PromptNotFoundError(
message=f"{id_name} invalide.",
details={id_name.lower(): id_str}
)
def _get_prompt_record(prompt_id: str, user_id: str) -> Tuple[CustomPrompt, bool]:
"""
Internal helper to fetch a prompt record from the database.
This is a shared function to avoid code duplication between
get_prompt_content and validate_prompt_access.
Args:
prompt_id: UUID of the prompt
user_id: UUID of the user (must own the prompt)
Returns:
Tuple of (CustomPrompt, was_logged) - was_logged indicates if access was already logged
Raises:
PromptNotFoundError: If prompt doesn't exist or doesn't belong to user
"""
# Validate UUIDs before querying database
_validate_uuid(prompt_id, "prompt_id")
_validate_uuid(user_id, "user_id")
try:
with get_sync_session() as session:
prompt = (
session.query(CustomPrompt)
.filter(CustomPrompt.id == prompt_id, CustomPrompt.user_id == user_id)
.first()
)
if not prompt:
raise PromptNotFoundError(
message="Prompt introuvable ou vous n'avez pas accès à cette ressource.",
details={"prompt_id": prompt_id}
)
return prompt, False
except PromptNotFoundError:
raise
except Exception as e:
logger.error(f"Error fetching prompt {prompt_id}: {e}")
raise PromptNotFoundError(
message="Erreur lors de la récupération du prompt.",
details={"prompt_id": prompt_id, "error": str(e)}
)
def get_prompt_content(prompt_id: str, user_id: str) -> str:
"""
Retrieve prompt content for a specific prompt owned by a user.
Args:
prompt_id: UUID of the prompt
user_id: UUID of the user (must own the prompt)
Returns:
The prompt content string
Raises:
PromptNotFoundError: If prompt doesn't exist or doesn't belong to user
"""
prompt, _ = _get_prompt_record(prompt_id, user_id)
logger.info(
f"Retrieved prompt '{prompt.name}' ({prompt_id}) for user {user_id}"
)
return prompt.content
def validate_prompt_access(prompt_id: str, user_id: str) -> bool:
"""
Validate that a prompt exists and belongs to the user.
Lightweight check before starting a translation job.
Does NOT log to avoid duplicate log entries when followed by get_prompt_content.
Args:
prompt_id: UUID of the prompt
user_id: UUID of the user (must own the prompt)
Returns:
True if prompt exists and belongs to user
Raises:
PromptNotFoundError: If prompt doesn't exist or doesn't belong to user
"""
_get_prompt_record(prompt_id, user_id)
return True