Unify hash request validation
This commit is contained in:
@@ -376,6 +376,20 @@ class HashService:
|
||||
return "", "file is outside configured model directories"
|
||||
return normalized_path, ""
|
||||
|
||||
async def _get_validated_hash_file_request(self, request):
|
||||
"""Read and validate the file request shared by hash endpoints."""
|
||||
data = await request.json()
|
||||
normalized_path, error = self.resolve_hash_file_request(data)
|
||||
if not error:
|
||||
return normalized_path, None
|
||||
|
||||
status = 400 if error == "file_path is required" else (
|
||||
403
|
||||
if error == "file is outside configured model directories"
|
||||
else 404
|
||||
)
|
||||
return "", self.web.json_response({"error": error}, status=status)
|
||||
|
||||
def write_calculated_hash_metadata(
|
||||
self,
|
||||
normalized_path,
|
||||
@@ -545,20 +559,11 @@ class HashService:
|
||||
|
||||
async def calculate_file_hash(self, request):
|
||||
"""Calculate SHA256 for a local model and persist sidecar metadata."""
|
||||
data = await request.json()
|
||||
|
||||
normalized_path, error = self.resolve_hash_file_request(data)
|
||||
if error == "file_path is required":
|
||||
return self.web.json_response(
|
||||
{"error": "file_path is required"}, status=400
|
||||
)
|
||||
if error:
|
||||
status = (
|
||||
403
|
||||
if error == "file is outside configured model directories"
|
||||
else 404
|
||||
)
|
||||
return self.web.json_response({"error": error}, status=status)
|
||||
normalized_path, error_response = await self._get_validated_hash_file_request(
|
||||
request
|
||||
)
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
sha256, sha256_source = self.calculate_sha256_with_progress(normalized_path)
|
||||
if not sha256:
|
||||
@@ -587,19 +592,11 @@ class HashService:
|
||||
|
||||
async def calculate_file_hash_start(self, request):
|
||||
"""Start SHA256 calculation in a background thread."""
|
||||
data = await request.json()
|
||||
normalized_path, error = self.resolve_hash_file_request(data)
|
||||
if error == "file_path is required":
|
||||
return self.web.json_response(
|
||||
{"error": "file_path is required"}, status=400
|
||||
)
|
||||
if error:
|
||||
status = (
|
||||
403
|
||||
if error == "file is outside configured model directories"
|
||||
else 404
|
||||
)
|
||||
return self.web.json_response({"error": error}, status=status)
|
||||
normalized_path, error_response = await self._get_validated_hash_file_request(
|
||||
request
|
||||
)
|
||||
if error_response:
|
||||
return error_response
|
||||
|
||||
self.hash_tracker.cleanup()
|
||||
progress_id = f"hash_{uuid.uuid4().hex}"
|
||||
|
||||
@@ -411,6 +411,40 @@ async def test_calculate_file_hash_writes_metadata_and_reports_source():
|
||||
assert written["metadata"]["file_name"] == "old"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"route",
|
||||
[
|
||||
"/model_resolver/calculate-file-hash",
|
||||
"/model_resolver/calculate-file-hash/start",
|
||||
],
|
||||
)
|
||||
async def test_hash_calculation_routes_share_file_request_validation(route):
|
||||
handlers, values = _build_hash_routes()
|
||||
handler = handlers[("POST", route)]
|
||||
|
||||
response = await handler(_request({}))
|
||||
assert response.status == 400
|
||||
assert json.loads(response.text) == {"error": "file_path is required"}
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp_dir:
|
||||
missing_path = os.path.join(temp_dir, "missing.safetensors")
|
||||
response = await handler(_request({"file_path": missing_path}))
|
||||
assert response.status == 404
|
||||
assert json.loads(response.text) == {"error": "file does not exist"}
|
||||
|
||||
outside_path = os.path.join(temp_dir, "outside.safetensors")
|
||||
with open(outside_path, "wb") as model_file:
|
||||
model_file.write(b"model")
|
||||
values["is_path_in_configured_model_roots"].return_value = False
|
||||
response = await handler(_request({"file_path": outside_path}))
|
||||
|
||||
assert response.status == 403
|
||||
assert json.loads(response.text) == {
|
||||
"error": "file is outside configured model directories"
|
||||
}
|
||||
|
||||
|
||||
def test_hash_service_reports_header_source_and_cancellation():
|
||||
sha256 = "e" * 64
|
||||
_, values = _build_hash_routes()
|
||||
|
||||
Reference in New Issue
Block a user