alternator: fix returning raw JSON errors

A couple of places in executor code leaked raw JSON errors to the user
instead of formulating a proper ValidationException message.
These places are now fixed, and the next patch in this series will
act as a regression checker, since all JSON errors will be returned
as SerializationException, not ValidationException instances.
This commit is contained in:
Piotr Sarna
2020-02-27 13:51:25 +01:00
committed by Pekka Enberg
parent 1be1cfc5d8
commit 6f8c70d54b
2 changed files with 19 additions and 13 deletions

View File

@@ -1677,15 +1677,18 @@ static std::string resolve_update_path(const parsed::path& p,
}
auto column_name = p.root();
if (column_name.size() > 0 && column_name[0] == '#') {
const rjson::value& expression_attribute_names = rjson::get(update_info, "ExpressionAttributeNames");
const rjson::value& value = rjson::get(expression_attribute_names, rjson::string_ref_type(column_name.c_str()));
if (!value.IsString()) {
const rjson::value* expression_attribute_names = rjson::find(update_info, "ExpressionAttributeNames");
if (!expression_attribute_names) {
throw api_error("ValidationException", "ExpressionAttributeNames are required by UpdateExpression");
}
const rjson::value* value = rjson::find(*expression_attribute_names, rjson::string_ref_type(column_name.c_str()));
if (!value || !value->IsString()) {
throw api_error("ValidationException",
format("ExpressionAttributeNames missing entry '{}' required by UpdateExpression",
column_name));
}
used_attribute_names.emplace(std::move(column_name));
column_name = value.GetString();
column_name = value->GetString();
}
const column_definition* cdef = schema->get_column_definition(to_bytes(column_name));
if (!allow_key_columns && cdef && cdef->is_primary_key()) {
@@ -1884,14 +1887,14 @@ rjson::value calculate_value(const parsed::value& v,
throw api_error("ValidationException",
format("ExpressionAttributeValues missing, entry '{}' required by {}", valref, caller));
}
const rjson::value& value = rjson::get(*expression_attribute_values, rjson::string_ref_type(valref.c_str()));
if (value.IsNull()) {
const rjson::value* value = rjson::find(*expression_attribute_values, rjson::string_ref_type(valref.c_str()));
if (!value || value->IsNull()) {
throw api_error("ValidationException",
format("ExpressionAttributeValues missing entry '{}' required by {}", valref, caller));
}
validate_value(value, "ExpressionAttributeValues");
validate_value(*value, "ExpressionAttributeValues");
used_attribute_values.emplace(std::move(valref));
return rjson::copy(value);
return rjson::copy(*value);
},
[&] (const parsed::value::function_call& f) -> rjson::value {
// TODO: use a lookup table here - for each function name a
@@ -2111,13 +2114,13 @@ static std::string resolve_projection_path(const parsed::path& p,
if (!expression_attribute_names) {
throw api_error("ValidationException", "ExpressionAttributeNames parameter not found");
}
const rjson::value& value = rjson::get(*expression_attribute_names, rjson::string_ref_type(column_name.c_str()));
if (!value.IsString()) {
const rjson::value* value = rjson::find(*expression_attribute_names, rjson::string_ref_type(column_name.c_str()));
if (!value || !value->IsString()) {
throw api_error("ValidationException",
format("ExpressionAttributeNames missing entry '{}' required by ProjectionExpression", column_name));
}
used_attribute_names.emplace(std::move(column_name));
column_name = value.GetString();
column_name = value->GetString();
}
// FIXME: this check will need to change when we support non-toplevel attributes
if (!seen_column_names.insert(column_name).second) {

View File

@@ -160,8 +160,11 @@ std::string type_to_string(data_type type) {
bytes get_key_column_value(const rjson::value& item, const column_definition& column) {
std::string column_name = column.name_as_text();
const rjson::value& key_typed_value = rjson::get(item, rjson::value::StringRefType(column_name.c_str()));
return get_key_from_typed_value(key_typed_value, column);
const rjson::value* key_typed_value = rjson::find(item, rjson::value::StringRefType(column_name.c_str()));
if (!key_typed_value) {
throw api_error("ValidationException", format("Key column {} not found", column_name));
}
return get_key_from_typed_value(*key_typed_value, column);
}
// Parses the JSON encoding for a key value, which is a map with a single