Improve DDB transaction validation (#5521)
This commit is contained in:
parent
8486646f2d
commit
696b809b5a
@ -323,3 +323,12 @@ class InvalidConversion(JsonRESTError):
|
||||
def __init__(self):
|
||||
er = "SerializationException"
|
||||
super().__init__(er, "NUMBER_VALUE cannot be converted to String")
|
||||
|
||||
|
||||
class TransactWriteSingleOpException(MockValidationException):
|
||||
there_can_be_only_one = (
|
||||
"TransactItems can only contain one of Check, Put, Update or Delete"
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(self.there_can_be_only_one)
|
||||
|
@ -32,6 +32,7 @@ from moto.dynamodb.exceptions import (
|
||||
StreamAlreadyEnabledException,
|
||||
MockValidationException,
|
||||
InvalidConversion,
|
||||
TransactWriteSingleOpException,
|
||||
)
|
||||
from moto.dynamodb.models.utilities import bytesize
|
||||
from moto.dynamodb.models.dynamo_type import DynamoType
|
||||
@ -1656,6 +1657,11 @@ class DynamoDBBackend(BaseBackend):
|
||||
|
||||
errors = [] # [(Code, Message, Item), ..]
|
||||
for item in transact_items:
|
||||
# check transact writes are not performing multiple operations
|
||||
# in the same item
|
||||
if len(list(item.keys())) > 1:
|
||||
raise TransactWriteSingleOpException
|
||||
|
||||
try:
|
||||
if "ConditionCheck" in item:
|
||||
item = item["ConditionCheck"]
|
||||
@ -1682,6 +1688,7 @@ class DynamoDBBackend(BaseBackend):
|
||||
item = item["Put"]
|
||||
attrs = item["Item"]
|
||||
table_name = item["TableName"]
|
||||
check_unicity(table_name, item)
|
||||
condition_expression = item.get("ConditionExpression", None)
|
||||
expression_attribute_names = item.get(
|
||||
"ExpressionAttributeNames", None
|
||||
|
@ -761,3 +761,42 @@ def test_query_begins_with_without_brackets():
|
||||
'Invalid KeyConditionExpression: Syntax error; token: "sk"'
|
||||
)
|
||||
err["Code"].should.equal("ValidationException")
|
||||
|
||||
|
||||
@mock_dynamodb
|
||||
def test_transact_write_items_multiple_operations_fail():
|
||||
|
||||
# Setup
|
||||
table_schema = {
|
||||
"KeySchema": [{"AttributeName": "id", "KeyType": "HASH"}],
|
||||
"AttributeDefinitions": [{"AttributeName": "id", "AttributeType": "S"}],
|
||||
}
|
||||
dynamodb = boto3.client("dynamodb", region_name="us-east-1")
|
||||
table_name = "test-table"
|
||||
dynamodb.create_table(
|
||||
TableName=table_name, BillingMode="PAY_PER_REQUEST", **table_schema
|
||||
)
|
||||
|
||||
# Execute
|
||||
with pytest.raises(ClientError) as exc:
|
||||
dynamodb.transact_write_items(
|
||||
TransactItems=[
|
||||
{
|
||||
"Put": {
|
||||
"Item": {"id": {"S": "test"}},
|
||||
"TableName": table_name,
|
||||
},
|
||||
"Delete": {
|
||||
"Key": {"id": {"S": "test"}},
|
||||
"TableName": table_name,
|
||||
},
|
||||
}
|
||||
]
|
||||
)
|
||||
# Verify
|
||||
err = exc.value.response["Error"]
|
||||
assert err["Code"] == "ValidationException"
|
||||
assert (
|
||||
err["Message"]
|
||||
== "TransactItems can only contain one of Check, Put, Update or Delete"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user