Allow context to be specified as JSON and not base64 JSON.

Remove retrieve tests that utilize url parameters since it is a POST endpoint.
pull/2960/head
derekpierre 2022-08-30 18:40:10 -04:00 committed by Kieran Prasch
parent 67f4f50751
commit d77fac4d39
7 changed files with 30 additions and 59 deletions

View File

@ -674,9 +674,9 @@ Parameters
+-------------------------------------------+---------------+----------------------------------------+ +-------------------------------------------+---------------+----------------------------------------+
| ``bob_verifying_key`` | String | Bob's verifying key encoded as hex. | | ``bob_verifying_key`` | String | Bob's verifying key encoded as hex. |
+-------------------------------------------+---------------+----------------------------------------+ +-------------------------------------------+---------------+----------------------------------------+
| ``context`` *(Optional)* | String | | Associated data required during | | ``context`` *(Optional)* | String | | Associated JSON data required during |
| | | | re-encryption e.g. data to satisfy | | | | | re-encryption e.g. data to satisfy |
| | | | conditions. | | | | | re-encryption conditions. |
+-------------------------------------------+---------------+----------------------------------------+ +-------------------------------------------+---------------+----------------------------------------+
@ -703,7 +703,7 @@ Parameters
because some Ursulas may have experienced a blip in connectivity. This is an optional optimization that provides because some Ursulas may have experienced a blip in connectivity. This is an optional optimization that provides
retry functionality that skips previously successful reencryption operations. retry functionality that skips previously successful reencryption operations.
* A *context* is associated data required during re-encryption. One such example is when a condition for re-encryption * A *context* is associated JSON data required during re-encryption. One such example is when a condition for re-encryption
requires proof of ownership of a wallet address; the *context* is used to provide the data and signature required for proof. requires proof of ownership of a wallet address; the *context* is used to provide the data and signature required for proof.

View File

@ -87,25 +87,20 @@ class Base64BytesRepresentation(BaseField, fields.Field):
raise InvalidInputData(f"Could not parse {self.name}: {e}") raise InvalidInputData(f"Could not parse {self.name}: {e}")
class Base64JSON(Base64BytesRepresentation): class JSON(BaseField, fields.Field):
"""Serializes/Deserializes JSON objects as base64 byte representation.""" """Serializes/Deserializes objects to/from JSON strings."""
def _serialize(self, value, attr, obj, **kwargs): def _serialize(self, value, attr, obj, **kwargs):
try: try:
value_json = json.dumps(value) value_json = json.dumps(value)
return value_json
except Exception as e: except Exception as e:
raise InvalidInputData( raise InvalidInputData(
f"Provided object type, {type(value)}, is not JSON serializable: {e}" f"Provided object type, {type(value)}, is not JSON serializable: {e}"
) )
else:
json_base64_bytes = super()._serialize(
value_json.encode(), attr, obj, **kwargs
)
return json_base64_bytes
def _deserialize(self, value, attr, data, **kwargs): def _deserialize(self, value, attr, data, **kwargs):
json_bytes = super()._deserialize(value, attr, data, **kwargs)
try: try:
return json.loads(json_bytes) result = json.loads(value)
return result
except Exception as e: except Exception as e:
raise InvalidInputData(f"Invalid JSON bytes: {e}") raise InvalidInputData(f"Invalid JSON: {e}")

View File

@ -160,7 +160,7 @@ class BobRetrieveCFrags(BaseSchema):
required=True)) required=True))
# optional # optional
context = base_fields.Base64JSON( context = base_fields.JSON(
required=False, required=False,
load_only=True, load_only=True,
click=click.option( click=click.option(

View File

@ -18,15 +18,17 @@
import json import json
import os import os
from base64 import b64encode from base64 import b64encode
from urllib.parse import urlencode
from nucypher_core import RetrievalKit from nucypher_core import RetrievalKit
from nucypher.characters.lawful import Enrico from nucypher.characters.lawful import Enrico
from nucypher.control.specifications.fields import Base64JSON from nucypher.control.specifications.fields import JSON
from nucypher.crypto.powers import DecryptingPower from nucypher.crypto.powers import DecryptingPower
from nucypher.policy.kits import PolicyMessageKit, RetrievalResult from nucypher.policy.kits import PolicyMessageKit, RetrievalResult
from nucypher.utilities.porter.control.specifications.fields import RetrievalResultSchema, RetrievalKit as RetrievalKitField from nucypher.utilities.porter.control.specifications.fields import (
RetrievalResultSchema,
RetrievalKit as RetrievalKitField,
)
from tests.utils.middleware import MockRestMiddleware from tests.utils.middleware import MockRestMiddleware
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -173,7 +175,7 @@ def test_retrieve_cfrags(blockchain_porter,
# #
# Use context # Use context
# #
context_field = Base64JSON() context_field = JSON()
multiple_retrieval_kits_params['context'] = context_field._serialize(random_context, attr=None, obj=None) multiple_retrieval_kits_params['context'] = context_field._serialize(random_context, attr=None, obj=None)
response = blockchain_porter_web_controller.post('/retrieve_cfrags', data=json.dumps( response = blockchain_porter_web_controller.post('/retrieve_cfrags', data=json.dumps(
@ -185,20 +187,6 @@ def test_retrieve_cfrags(blockchain_porter,
assert retrieval_results assert retrieval_results
assert len(retrieval_results) == 2 assert len(retrieval_results) == 2
#
# Try same retrieval (with multiple retrieval kits) using query parameters
#
url_retrieve_params = dict(multiple_retrieval_kits_params) # use multiple kit params from above
# adjust parameter for url query parameter list format
url_retrieve_params['retrieval_kits'] = ",".join(url_retrieve_params['retrieval_kits']) # adjust for list
response = blockchain_porter_web_controller.post(f'/retrieve_cfrags'
f'?{urlencode(url_retrieve_params)}')
assert response.status_code == 200
response_data = json.loads(response.data)
retrieval_results = response_data['result']['retrieval_results']
assert retrieval_results
assert len(retrieval_results) == 2
# #
# Failure # Failure
# #

View File

@ -18,15 +18,17 @@
import json import json
from base64 import b64encode from base64 import b64encode
from urllib.parse import urlencode
from nucypher_core import RetrievalKit from nucypher_core import RetrievalKit
from nucypher.characters.lawful import Enrico from nucypher.characters.lawful import Enrico
from nucypher.control.specifications.fields import Base64JSON from nucypher.control.specifications.fields import JSON
from nucypher.crypto.powers import DecryptingPower from nucypher.crypto.powers import DecryptingPower
from nucypher.policy.kits import PolicyMessageKit, RetrievalResult from nucypher.policy.kits import PolicyMessageKit, RetrievalResult
from nucypher.utilities.porter.control.specifications.fields import RetrievalResultSchema, RetrievalKit as RetrievalKitField from nucypher.utilities.porter.control.specifications.fields import (
RetrievalResultSchema,
RetrievalKit as RetrievalKitField,
)
from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest from tests.utils.policy import retrieval_request_setup, retrieval_params_decode_from_rest
@ -174,7 +176,7 @@ def test_retrieve_cfrags(federated_porter,
# #
# Use context # Use context
# #
context_field = Base64JSON() context_field = JSON()
multiple_retrieval_kits_params['context'] = context_field._serialize(random_context, attr=None, obj=None) multiple_retrieval_kits_params['context'] = context_field._serialize(random_context, attr=None, obj=None)
response = federated_porter_web_controller.post('/retrieve_cfrags', data=json.dumps(multiple_retrieval_kits_params)) response = federated_porter_web_controller.post('/retrieve_cfrags', data=json.dumps(multiple_retrieval_kits_params))
assert response.status_code == 200 assert response.status_code == 200
@ -184,20 +186,6 @@ def test_retrieve_cfrags(federated_porter,
assert retrieval_results assert retrieval_results
assert len(retrieval_results) == 4 assert len(retrieval_results) == 4
#
# Try same retrieval (with multiple retrieval kits) using query parameters
#
url_retrieve_params = dict(multiple_retrieval_kits_params) # use multiple kit params from above
# adjust parameter for url query parameter list format
url_retrieve_params['retrieval_kits'] = ",".join(url_retrieve_params['retrieval_kits'])
response = federated_porter_web_controller.post(f'/retrieve_cfrags'
f'?{urlencode(url_retrieve_params)}')
assert response.status_code == 200
response_data = json.loads(response.data)
retrieval_results = response_data['result']['retrieval_results']
assert retrieval_results
assert len(retrieval_results) == 4
# #
# Failure # Failure
# #

View File

@ -22,7 +22,7 @@ import pytest
from nucypher.control.specifications.exceptions import InvalidInputData from nucypher.control.specifications.exceptions import InvalidInputData
from nucypher.control.specifications.fields import ( from nucypher.control.specifications.fields import (
Base64BytesRepresentation, Base64BytesRepresentation,
Base64JSON, JSON,
PositiveInteger, PositiveInteger,
String, String,
StringList, StringList,
@ -74,7 +74,7 @@ def test_base64_representation_field():
field._deserialize(value=b"raw bytes with non base64 chars ?&^%", attr=None, data=None) field._deserialize(value=b"raw bytes with non base64 chars ?&^%", attr=None, data=None)
def test_base64_json_field(): def test_json_field():
# test data # test data
dict_data = { dict_data = {
"domain": {"name": "tdec", "version": 1, "chainId": 1, "salt": "blahblahblah"}, "domain": {"name": "tdec", "version": 1, "chainId": 1, "salt": "blahblahblah"},
@ -94,10 +94,10 @@ def test_base64_json_field():
# test serialization/deserialization of data # test serialization/deserialization of data
test_data = [dict_data, list_data, str_data, num_data, bool_data] test_data = [dict_data, list_data, str_data, num_data, bool_data]
field = Base64JSON() field = JSON()
for d in test_data: for d in test_data:
serialized = field._serialize(value=d, attr=None, obj=None) serialized = field._serialize(value=d, attr=None, obj=None)
assert serialized == b64encode(json.dumps(d).encode()).decode() assert serialized == json.dumps(d)
deserialized = field._deserialize(value=serialized, attr=None, data=None) deserialized = field._deserialize(value=serialized, attr=None, data=None)
assert deserialized == d assert deserialized == d
@ -109,5 +109,5 @@ def test_base64_json_field():
with pytest.raises(InvalidInputData): with pytest.raises(InvalidInputData):
# attempt to deserialize invalid data # attempt to deserialize invalid data
field._deserialize( field._deserialize(
value=b"raw bytes with non base64 chars ?&^%", attr=None, data=None value=b"raw bytes", attr=None, data=None
) )

View File

@ -24,7 +24,7 @@ from nucypher_core import MessageKit, RetrievalKit
from nucypher.characters.control.specifications.fields import Key, TreasureMap from nucypher.characters.control.specifications.fields import Key, TreasureMap
from nucypher.characters.lawful import Enrico from nucypher.characters.lawful import Enrico
from nucypher.control.specifications.fields import Base64JSON from nucypher.control.specifications.fields import JSON
from nucypher.crypto.powers import DecryptingPower from nucypher.crypto.powers import DecryptingPower
from nucypher.utilities.porter.control.specifications.fields import ( from nucypher.utilities.porter.control.specifications.fields import (
RetrievalKit as RetrievalKitField, RetrievalKit as RetrievalKitField,
@ -76,7 +76,7 @@ def retrieval_request_setup(enacted_policy,
) )
# context is optional # context is optional
if context: if context:
retrieval_params["context"] = encode_bytes(Base64JSON, context) retrieval_params["context"] = encode_bytes(JSON, context)
return retrieval_params, message_kit return retrieval_params, message_kit
@ -98,7 +98,7 @@ def retrieval_params_decode_from_rest(retrieval_params: Dict) -> Dict:
# context is optional # context is optional
if "context" in retrieval_params: if "context" in retrieval_params:
decoded_params["context"] = decode_bytes( decoded_params["context"] = decode_bytes(
Base64JSON, retrieval_params["context"] JSON, retrieval_params["context"]
) )
return decoded_params return decoded_params