Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions autobot-backend/api/advanced_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from auth_middleware import check_admin_permission
from autobot_shared.error_boundaries import ErrorCategory, with_error_handling
from constants.threshold_constants import TimingConstants
from constants.error_constants import ERR_SESSION_NOT_FOUND
from desktop_streaming_manager import desktop_streaming
from enhanced_memory_manager_async import TaskPriority
from takeover_manager import TakeoverTrigger, takeover_manager
Expand Down Expand Up @@ -127,7 +128,7 @@ async def terminate_streaming_session(
logger.info("Desktop streaming session terminated: %s", session_id)
return {"success": True, "session_id": session_id}
else:
raise HTTPException(status_code=404, detail="Session not found")
raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)


@with_error_handling(
Expand Down Expand Up @@ -358,7 +359,7 @@ async def complete_takeover_session(
if success:
return {"success": True, "session_id": session_id, "status": "completed"}
else:
raise HTTPException(status_code=404, detail="Session not found")
raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)


@with_error_handling(
Expand Down
5 changes: 3 additions & 2 deletions autobot-backend/api/agent_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@
from typing import Dict, Optional

from fastapi import APIRouter, Depends, HTTPException
from constants.error_constants import ERR_SESSION_NOT_FOUND
from pydantic import BaseModel, Field

from auth_middleware import get_current_user
Expand Down Expand Up @@ -492,7 +493,7 @@ async def get_agent_terminal_session(
session_info = await service.get_session_info(session_id)

if not session_info:
raise HTTPException(status_code=404, detail="Session not found")
raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)

return {
"status": "success",
Expand All @@ -519,7 +520,7 @@ async def delete_agent_terminal_session(
success = await service.close_session(session_id)

if not success:
raise HTTPException(status_code=404, detail="Session not found")
raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)

return {
"status": "deleted",
Expand Down
50 changes: 25 additions & 25 deletions autobot-backend/api/api_endpoint_migrations_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -3910,7 +3910,7 @@ def test_scan_for_unimported_files_preserves_httpexception(self):

# Should preserve directory validation
assert "if not scan_path.exists():" in source
assert "Directory not found" in source
assert ERR_DIRECTORY_NOT_FOUND in source
assert "status_code=404" in source

def test_scan_for_unimported_files_preserves_import_tracker(self):
Expand Down Expand Up @@ -4520,7 +4520,7 @@ def test_list_files_preserves_httpexceptions(self):
'status_code=403, detail="Insufficient permissions for file operations"'
in source
)
assert 'status_code=404, detail="Directory not found"' in source
assert 'status_code=404, detail=ERR_DIRECTORY_NOT_FOUND' in source
assert 'status_code=400, detail="Path is not a directory"' in source

def test_list_files_preserves_business_logic(self):
Expand Down Expand Up @@ -4722,7 +4722,7 @@ def test_download_file_preserves_httpexceptions(self):

source = inspect.getsource(download_file)
assert "status_code=403" in source
assert 'status_code=404, detail="File not found"' in source
assert 'status_code=404, detail=ERR_FILE_NOT_FOUND' in source
assert 'status_code=400, detail="Path is not a file"' in source

def test_download_file_preserves_business_logic(self):
Expand Down Expand Up @@ -4771,7 +4771,7 @@ def test_view_file_preserves_httpexceptions(self):

source = inspect.getsource(view_file)
assert "status_code=403" in source
assert 'status_code=404, detail="File not found"' in source
assert 'status_code=404, detail=ERR_FILE_NOT_FOUND' in source
assert 'status_code=400, detail="Path is not a file"' in source

def test_view_file_preserves_business_logic(self):
Expand Down Expand Up @@ -4850,7 +4850,7 @@ def test_rename_file_preserves_httpexceptions(self):
source = inspect.getsource(rename_file_or_directory)
assert "status_code=403" in source
assert 'status_code=400, detail="Invalid file/directory name"' in source
assert 'status_code=404, detail="File or directory not found"' in source
assert 'status_code=404, detail=ERR_FILE_OR_DIR_NOT_FOUND' in source
assert "status_code=409" in source

def test_rename_file_preserves_business_logic(self):
Expand Down Expand Up @@ -4899,7 +4899,7 @@ def test_preview_file_preserves_httpexceptions(self):

source = inspect.getsource(preview_file)
assert "status_code=403" in source
assert 'status_code=404, detail="File not found"' in source
assert 'status_code=404, detail=ERR_FILE_NOT_FOUND' in source
assert 'status_code=400, detail="Path is not a file"' in source

def test_preview_file_preserves_business_logic(self):
Expand Down Expand Up @@ -4977,7 +4977,7 @@ def test_delete_file_preserves_httpexceptions(self):

source = inspect.getsource(delete_file)
assert "status_code=403" in source
assert 'status_code=404, detail="File or directory not found"' in source
assert 'status_code=404, detail=ERR_FILE_OR_DIR_NOT_FOUND' in source

def test_delete_file_preserves_business_logic(self):
import inspect
Expand Down Expand Up @@ -5105,7 +5105,7 @@ def test_get_directory_tree_preserves_httpexceptions(self):

source = inspect.getsource(get_directory_tree)
assert "status_code=403" in source
assert 'status_code=404, detail="Directory not found"' in source
assert 'status_code=404, detail=ERR_DIRECTORY_NOT_FOUND' in source
assert 'status_code=400, detail="Path is not a directory"' in source

def test_get_directory_tree_preserves_business_logic(self):
Expand Down Expand Up @@ -5269,7 +5269,7 @@ def test_get_workflow_details_preserves_httpexception(self):
from api.workflow import get_workflow_details

source = inspect.getsource(get_workflow_details)
assert 'status_code=404, detail="Workflow not found"' in source
assert 'status_code=404, detail=ERR_WORKFLOW_NOT_FOUND' in source

def test_get_workflow_details_preserves_business_logic(self):
import inspect
Expand Down Expand Up @@ -5343,7 +5343,7 @@ def test_get_workflow_status_preserves_httpexception(self):
from api.workflow import get_workflow_status

source = inspect.getsource(get_workflow_status)
assert 'status_code=404, detail="Workflow not found"' in source
assert 'status_code=404, detail=ERR_WORKFLOW_NOT_FOUND' in source

def test_get_workflow_status_preserves_business_logic(self):
import inspect
Expand Down Expand Up @@ -5389,7 +5389,7 @@ def test_approve_workflow_step_preserves_httpexceptions(self):
from api.workflow import approve_workflow_step

source = inspect.getsource(approve_workflow_step)
assert 'status_code=404, detail="Workflow not found"' in source
assert 'status_code=404, detail=ERR_WORKFLOW_NOT_FOUND' in source
assert 'status_code=404, detail="No pending approval' in source

def test_approve_workflow_step_preserves_business_logic(self):
Expand Down Expand Up @@ -8403,7 +8403,7 @@ def test_get_terminal_session_business_logic_preserved(self):
"config = session_manager.session_configs.get(session_id)", source
)
self.assertIn(
'raise HTTPException(status_code=404, detail="Session not found")', source
'raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)', source
)
self.assertIn("is_active = session_manager.has_connection(session_id)", source)
self.assertIn("stats = {}", source)
Expand Down Expand Up @@ -8468,7 +8468,7 @@ def test_delete_terminal_session_business_logic_preserved(self):
"config = session_manager.session_configs.get(session_id)", source
)
self.assertIn(
'raise HTTPException(status_code=404, detail="Session not found")', source
'raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)', source
)
self.assertIn("if session_manager.has_connection(session_id):", source)
self.assertIn("await session_manager.close_connection(session_id)", source)
Expand Down Expand Up @@ -8793,7 +8793,7 @@ def test_get_terminal_command_history_business_logic_preserved(self):
)
self.assertIn("if not config:", source)
self.assertIn(
'raise HTTPException(status_code=404, detail="Session not found")', source
'raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)', source
)
self.assertIn("is_active = session_manager.has_connection(session_id)", source)
self.assertIn("if not is_active:", source)
Expand Down Expand Up @@ -8882,7 +8882,7 @@ def test_get_session_audit_log_business_logic_preserved(self):
)
self.assertIn("if not config:", source)
self.assertIn(
'raise HTTPException(status_code=404, detail="Session not found")', source
'raise HTTPException(status_code=404, detail=ERR_SESSION_NOT_FOUND)', source
)
self.assertIn('"session_id": session_id', source)
self.assertIn('config.get("enable_logging", False)', source)
Expand Down Expand Up @@ -10631,7 +10631,7 @@ def test_batch65_httpexception_preserved(self):
f"{func.__name__} should preserve HTTPException raises",
)
self.assertIn(
'"Session not found"',
'ERR_SESSION_NOT_FOUND',
source,
f"{func.__name__} should check for session existence",
)
Expand Down Expand Up @@ -10731,7 +10731,7 @@ def test_navigate_session_httpexception_preserved(self):

source = inspect.getsource(navigate_session)
self.assertIn("HTTPException", source)
self.assertIn('"Session not found"', source)
self.assertIn('ERR_SESSION_NOT_FOUND', source)
# Should check session existence
self.assertIn("if not session:", source)

Expand Down Expand Up @@ -10767,7 +10767,7 @@ def test_get_browser_info_httpexception_preserved(self):

source = inspect.getsource(get_browser_info)
self.assertIn("HTTPException", source)
self.assertIn('"Session not found"', source)
self.assertIn('ERR_SESSION_NOT_FOUND', source)
# Should check session existence (after special chat-browser handling)
self.assertIn("if not session:", source)

Expand Down Expand Up @@ -10859,7 +10859,7 @@ def test_batch66_httpexception_preservation(self):
f"{func.__name__} should preserve HTTPException raises",
)
self.assertIn(
'"Session not found"',
'ERR_SESSION_NOT_FOUND',
source,
f"{func.__name__} should check for session existence",
)
Expand Down Expand Up @@ -10961,7 +10961,7 @@ def test_get_agent_terminal_session_httpexception_preserved(self):

source = inspect.getsource(get_agent_terminal_session)
self.assertIn("HTTPException", source)
self.assertIn('"Session not found"', source)
self.assertIn('ERR_SESSION_NOT_FOUND', source)
self.assertIn("status_code=404", source)
# Should check session existence
self.assertIn("if not session_info:", source)
Expand Down Expand Up @@ -11093,7 +11093,7 @@ def test_delete_agent_terminal_session_httpexception_preserved(self):

source = inspect.getsource(delete_agent_terminal_session)
self.assertIn("HTTPException", source)
self.assertIn('"Session not found"', source)
self.assertIn('ERR_SESSION_NOT_FOUND', source)
self.assertIn("status_code=404", source)
# Should check session close success
self.assertIn("if not success:", source)
Expand Down Expand Up @@ -11237,7 +11237,7 @@ def test_batch68_httpexception_preservation(self):
source,
"delete_agent_terminal_session should preserve HTTPException raises",
)
self.assertIn('"Session not found"', source)
self.assertIn('ERR_SESSION_NOT_FOUND', source)

def test_batch68_business_logic_preservation(self):
"""Test batch 68 preserves all business logic"""
Expand Down Expand Up @@ -16538,7 +16538,7 @@ def test_batch_94_terminate_streaming_session_preserves_http_exception(self):
# Should preserve 404 HTTPException for business logic
self.assertIn("HTTPException", source)
self.assertIn("status_code=404", source)
self.assertIn("Session not found", source)
self.assertIn(ERR_SESSION_NOT_FOUND, source)

def test_batch_94_list_streaming_sessions_has_decorator(self):
"""Verify list_streaming_sessions has @with_error_handling decorator"""
Expand Down Expand Up @@ -16811,7 +16811,7 @@ def test_batch_95_complete_takeover_session_preserves_http_exception(self):
# Should preserve 404 HTTPException for business logic
self.assertIn("HTTPException", source)
self.assertIn("status_code=404", source)
self.assertIn("Session not found", source)
self.assertIn(ERR_SESSION_NOT_FOUND, source)
# Should NOT have outer try-catch wrapper
try_count = source.count("try:")
self.assertEqual(
Expand Down Expand Up @@ -17283,7 +17283,7 @@ def test_batch_97_get_workflow_details_preserves_404(self):
# Should preserve 404 HTTPException
self.assertIn("HTTPException", source)
self.assertIn("status_code=404", source)
self.assertIn("Workflow not found", source)
self.assertIn(ERR_WORKFLOW_NOT_FOUND, source)
# Should have NO try-catch blocks (Mixed Pattern with direct checks)
try_count = source.count("try:")
self.assertEqual(
Expand Down
5 changes: 3 additions & 2 deletions autobot-backend/api/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

from auth_middleware import auth_middleware
from autobot_shared.error_boundaries import ErrorCategory, with_error_handling
from constants.error_constants import ERR_INVALID_CREDENTIALS, ERR_INVALID_TOKEN
from user_management.database import db_session_context
from user_management.services.user_service import UserService

Expand Down Expand Up @@ -184,7 +185,7 @@ async def _authenticate_and_build_user_data(
ip_address=ip_address,
)
if not user:
raise HTTPException(status_code=401, detail="Invalid username or password")
raise HTTPException(status_code=401, detail=ERR_INVALID_CREDENTIALS)
user_data = {
"username": user.username,
"user_id": str(user.id),
Expand Down Expand Up @@ -554,7 +555,7 @@ def _decode_refresh_token(token: str) -> Dict:
options={"verify_exp": False},
)
except pyjwt.InvalidTokenError as exc:
raise HTTPException(status_code=401, detail="Invalid token") from exc
raise HTTPException(status_code=401, detail=ERR_INVALID_TOKEN) from exc

exp = payload.get("exp")
if exp:
Expand Down
24 changes: 15 additions & 9 deletions autobot-backend/api/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
from auth_middleware import auth_middleware
from autobot_shared.error_boundaries import ErrorCategory, with_error_handling
from autobot_shared.security.path_validator import validate_relative_path
from constants.error_constants import (
ERR_DIRECTORY_NOT_FOUND,
ERR_FILE_NOT_FOUND,
ERR_FILE_OR_DIR_NOT_FOUND,
ERR_PATH_NOT_FOUND,
)
from security_layer import SecurityLayer
from utils.io_executor import run_in_file_executor
from utils.path_validation import is_invalid_name
Expand Down Expand Up @@ -415,7 +421,7 @@ async def list_files(request: Request, path: str = ""):

# Issue #358/#718: Use dedicated executor for non-blocking file I/O
if not await run_in_file_executor(target_path.exists):
raise HTTPException(status_code=404, detail="Directory not found")
raise HTTPException(status_code=404, detail=ERR_DIRECTORY_NOT_FOUND)

if not await run_in_file_executor(target_path.is_dir):
raise HTTPException(status_code=400, detail="Path is not a directory")
Expand Down Expand Up @@ -757,7 +763,7 @@ async def download_file(request: Request, path: str):

# Issue #358/#718: Use dedicated executor for non-blocking file I/O
if not await run_in_file_executor(target_file.exists):
raise HTTPException(status_code=404, detail="File not found")
raise HTTPException(status_code=404, detail=ERR_FILE_NOT_FOUND)

if not await run_in_file_executor(target_file.is_file):
raise HTTPException(status_code=400, detail="Path is not a file")
Expand Down Expand Up @@ -814,7 +820,7 @@ async def view_file(request: Request, path: str):

# Issue #358/#718: Use dedicated executor for non-blocking file I/O
if not await run_in_file_executor(target_file.exists):
raise HTTPException(status_code=404, detail="File not found")
raise HTTPException(status_code=404, detail=ERR_FILE_NOT_FOUND)

if not await run_in_file_executor(target_file.is_file):
raise HTTPException(status_code=400, detail="Path is not a file")
Expand Down Expand Up @@ -898,7 +904,7 @@ async def _validate_rename_paths(source_path: Path, new_name: str) -> Path:
Issue #620.
"""
if not await run_in_file_executor(source_path.exists):
raise HTTPException(status_code=404, detail="File or directory not found")
raise HTTPException(status_code=404, detail=ERR_FILE_OR_DIR_NOT_FOUND)

target_path = source_path.parent / new_name

Expand Down Expand Up @@ -1024,7 +1030,7 @@ async def preview_file(request: Request, path: str):

# Issue #358/#718: Use dedicated executor for non-blocking file I/O
if not await run_in_file_executor(target_file.exists):
raise HTTPException(status_code=404, detail="File not found")
raise HTTPException(status_code=404, detail=ERR_FILE_NOT_FOUND)

if not await run_in_file_executor(target_file.is_file):
raise HTTPException(status_code=400, detail="Path is not a file")
Expand Down Expand Up @@ -1076,7 +1082,7 @@ async def delete_file(request: Request, path: str):
target_path = validate_and_resolve_path(path)

if not await run_in_file_executor(target_path.exists):
raise HTTPException(status_code=404, detail="File or directory not found")
raise HTTPException(status_code=404, detail=ERR_FILE_OR_DIR_NOT_FOUND)

security_layer = get_security_layer(request)
is_file = await run_in_file_executor(target_path.is_file)
Expand Down Expand Up @@ -1191,7 +1197,7 @@ async def get_directory_tree(request: Request, path: str = ""):

# Issue #358/#718: Use dedicated executor for non-blocking file I/O
if not await run_in_file_executor(target_path.exists):
raise HTTPException(status_code=404, detail="Directory not found")
raise HTTPException(status_code=404, detail=ERR_DIRECTORY_NOT_FOUND)

if not await run_in_file_executor(target_path.is_dir):
raise HTTPException(status_code=400, detail="Path is not a directory")
Expand Down Expand Up @@ -1346,7 +1352,7 @@ async def admin_list_directory(path: str = "/home/autobot") -> dict: # noqa: ss
"""
target = _validate_admin_path(path)
if not target.exists():
raise HTTPException(status_code=404, detail="Path not found")
raise HTTPException(status_code=404, detail=ERR_PATH_NOT_FOUND)
if not target.is_dir():
raise HTTPException(status_code=400, detail="Path is not a directory")
try:
Expand All @@ -1366,7 +1372,7 @@ async def admin_read_file(path: str) -> dict:
"""
target = _validate_admin_path(path)
if not target.exists():
raise HTTPException(status_code=404, detail="File not found")
raise HTTPException(status_code=404, detail=ERR_FILE_NOT_FOUND)
if not target.is_file():
raise HTTPException(status_code=400, detail="Path is not a file")
if target.stat().st_size > _ADMIN_MAX_READ_BYTES:
Expand Down
Loading
Loading