mirror of
https://github.com/bigchaindb/bigchaindb.git
synced 2024-10-13 13:34:05 +00:00
Merge branch 'bug/1702/invalid-asset-data-keys'
This commit is contained in:
commit
293f7ec9e4
@ -1,7 +1,10 @@
|
|||||||
import time
|
import time
|
||||||
|
import re
|
||||||
import rapidjson
|
import rapidjson
|
||||||
|
|
||||||
|
import bigchaindb
|
||||||
|
from bigchaindb.common.exceptions import ValidationError
|
||||||
|
|
||||||
|
|
||||||
def gen_timestamp():
|
def gen_timestamp():
|
||||||
"""The Unix time, rounded to the nearest second.
|
"""The Unix time, rounded to the nearest second.
|
||||||
@ -46,3 +49,70 @@ def deserialize(data):
|
|||||||
string.
|
string.
|
||||||
"""
|
"""
|
||||||
return rapidjson.loads(data)
|
return rapidjson.loads(data)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_txn_obj(obj_name, obj, key, validation_fun):
|
||||||
|
"""Validates value associated to `key` in `obj` by applying
|
||||||
|
`validation_fun`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj_name (str): name for `obj` being validated.
|
||||||
|
obj (dict): dictonary object.
|
||||||
|
key (str): key to be validated in `obj`.
|
||||||
|
validation_fun (function): function used to validate the value
|
||||||
|
of `key`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None: indicates validation successfull
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValidationError: `validation_fun` will raise this error on failure
|
||||||
|
"""
|
||||||
|
backend = bigchaindb.config['database']['backend']
|
||||||
|
|
||||||
|
if backend == 'mongodb':
|
||||||
|
data = obj.get(key, {}) or {}
|
||||||
|
validate_all_keys(obj_name, data, validation_fun)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_all_keys(obj_name, obj, validation_fun):
|
||||||
|
"""Validates all (nested) keys in `obj` by using `validation_fun`
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj_name (str): name for `obj` being validated.
|
||||||
|
obj (dict): dictonary object.
|
||||||
|
validation_fun (function): function used to validate the value
|
||||||
|
of `key`.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None: indicates validation successfull
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValidationError: `validation_fun` will raise this error on failure
|
||||||
|
"""
|
||||||
|
for key, value in obj.items():
|
||||||
|
validation_fun(obj_name, key)
|
||||||
|
if type(value) is dict:
|
||||||
|
validate_all_keys(obj_name, value, validation_fun)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def validate_key(obj_name, key):
|
||||||
|
"""Check if `key` contains ".", "$" or null characters
|
||||||
|
https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj_name (str): object name to use when raising exception
|
||||||
|
key (str): key to validated
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
None: indicates validation successfull
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValidationError: raise execption incase of regex match.
|
||||||
|
"""
|
||||||
|
if re.search(r'^[$]|\.|\x00', key):
|
||||||
|
error_str = ('Invalid key name "{}" in {} object. The '
|
||||||
|
'key name cannot contain characters '
|
||||||
|
'".", "$" or null characters').format(key, obj_name)
|
||||||
|
raise ValidationError(error_str) from ValueError()
|
||||||
|
@ -8,7 +8,8 @@ from bigchaindb.common.exceptions import (InvalidHash, InvalidSignature,
|
|||||||
SybilError,
|
SybilError,
|
||||||
DuplicateTransaction)
|
DuplicateTransaction)
|
||||||
from bigchaindb.common.transaction import Transaction
|
from bigchaindb.common.transaction import Transaction
|
||||||
from bigchaindb.common.utils import gen_timestamp, serialize
|
from bigchaindb.common.utils import (gen_timestamp, serialize,
|
||||||
|
validate_txn_obj, validate_key)
|
||||||
from bigchaindb.common.schema import validate_transaction_schema
|
from bigchaindb.common.schema import validate_transaction_schema
|
||||||
|
|
||||||
|
|
||||||
@ -84,6 +85,8 @@ class Transaction(Transaction):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def from_dict(cls, tx_body):
|
def from_dict(cls, tx_body):
|
||||||
validate_transaction_schema(tx_body)
|
validate_transaction_schema(tx_body)
|
||||||
|
validate_txn_obj('asset', tx_body['asset'], 'data', validate_key)
|
||||||
|
validate_txn_obj('metadata', tx_body, 'metadata', validate_key)
|
||||||
return super().from_dict(tx_body)
|
return super().from_dict(tx_body)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -47,6 +47,41 @@ def test_post_create_transaction_endpoint(b, client):
|
|||||||
assert res.json['outputs'][0]['public_keys'][0] == user_pub
|
assert res.json['outputs'][0]['public_keys'][0] == user_pub
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("field", ['asset', 'metadata'])
|
||||||
|
@pytest.mark.parametrize("value,err_key,expected_status_code", [
|
||||||
|
({'bad.key': 'v'}, 'bad.key', 400),
|
||||||
|
({'$bad.key': 'v'}, '$bad.key', 400),
|
||||||
|
({'$badkey': 'v'}, '$badkey', 400),
|
||||||
|
({'bad\x00key': 'v'}, 'bad\x00key', 400),
|
||||||
|
({'good_key': {'bad.key': 'v'}}, 'bad.key', 400),
|
||||||
|
({'good_key': 'v'}, 'good_key', 202)
|
||||||
|
])
|
||||||
|
@pytest.mark.bdb
|
||||||
|
def test_post_create_transaction_with_invalid_key(b, client, field, value,
|
||||||
|
err_key, expected_status_code):
|
||||||
|
from bigchaindb.models import Transaction
|
||||||
|
from bigchaindb.backend.mongodb.connection import MongoDBConnection
|
||||||
|
user_priv, user_pub = crypto.generate_key_pair()
|
||||||
|
|
||||||
|
if isinstance(b.connection, MongoDBConnection):
|
||||||
|
if field == 'asset':
|
||||||
|
tx = Transaction.create([user_pub], [([user_pub], 1)],
|
||||||
|
asset=value)
|
||||||
|
elif field == 'metadata':
|
||||||
|
tx = Transaction.create([user_pub], [([user_pub], 1)],
|
||||||
|
metadata=value)
|
||||||
|
tx = tx.sign([user_priv])
|
||||||
|
res = client.post(TX_ENDPOINT, data=json.dumps(tx.to_dict()))
|
||||||
|
|
||||||
|
assert res.status_code == expected_status_code
|
||||||
|
if res.status_code == 400:
|
||||||
|
expected_error_message = (
|
||||||
|
'Invalid transaction (ValidationError): Invalid key name "{}" '
|
||||||
|
'in {} object. The key name cannot contain characters '
|
||||||
|
'".", "$" or null characters').format(err_key, field)
|
||||||
|
assert res.json['message'] == expected_error_message
|
||||||
|
|
||||||
|
|
||||||
@patch('bigchaindb.web.views.base.logger')
|
@patch('bigchaindb.web.views.base.logger')
|
||||||
def test_post_create_transaction_with_invalid_id(mock_logger, b, client):
|
def test_post_create_transaction_with_invalid_id(mock_logger, b, client):
|
||||||
from bigchaindb.common.exceptions import InvalidHash
|
from bigchaindb.common.exceptions import InvalidHash
|
||||||
|
Loading…
x
Reference in New Issue
Block a user