Skip to content

Commit

Permalink
input parameter validation via middleware
Browse files Browse the repository at this point in the history
Signed-off-by: sklump <[email protected]>
  • Loading branch information
sklump committed Apr 24, 2020
1 parent f069b78 commit 71ad41d
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 40 deletions.
17 changes: 15 additions & 2 deletions aries_cloudagent/admin/tests/test_admin_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from aiohttp import web
from asynctest import TestCase as AsyncTestCase
from asynctest.mock import patch
from asynctest.mock import CoroutineMock, patch

from ...config.default_context import DefaultContextBuilder
from ...config.injection_context import InjectionContext
Expand All @@ -12,7 +13,7 @@
from ...core.protocol_registry import ProtocolRegistry
from ...transport.outbound.message import OutboundMessage

from ..server import AdminServer
from ..server import AdminServer, AdminSetupError


class TestAdminServerBasic(AsyncTestCase):
Expand Down Expand Up @@ -64,6 +65,11 @@ async def test_start_stop(self):
await server.start()
await server.stop()

with patch.object(web.TCPSite, "start", CoroutineMock()) as mock_start:
mock_start.side_effect = OSError("Failure to launch")
with self.assertRaises(AdminSetupError):
await self.get_admin_server(settings).start()

async def test_responder_send(self):
message = OutboundMessage(payload="{}")
admin_server = self.get_admin_server()
Expand All @@ -75,14 +81,21 @@ async def test_responder_webhook(self):
admin_server = self.get_admin_server()
test_url = "target_url"
test_attempts = 99
admin_server.add_webhook_target(test_url, max_attempts=test_attempts)
admin_server.add_webhook_target(
target_url=test_url,
topic_filter=["*"], # cover vacuous filter
max_attempts=test_attempts,
)
test_topic = "test_topic"
test_payload = {"test": "TEST"}
await admin_server.responder.send_webhook(test_topic, test_payload)
assert self.webhook_results == [
(test_topic, test_payload, test_url, test_attempts)
]

admin_server.remove_webhook_target(target_url=test_url)
assert test_url not in admin_server.webhook_targets

async def test_import_routes(self):
# this test just imports all default admin routes
# for routes with associated tests, this shouldn't make a difference in coverage
Expand Down
16 changes: 11 additions & 5 deletions aries_cloudagent/ledger/tests/test_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ def setUp(self):
self.test_endpoint = "http://localhost:8021"

async def test_missing_ledger(self):
request = async_mock.MagicMock()
request.app = self.app
request = async_mock.MagicMock(
app=self.app,
)
self.context.injector.clear_binding(BaseLedger)

with self.assertRaises(HTTPForbidden):
Expand Down Expand Up @@ -80,9 +81,14 @@ async def test_get_endpoint_no_did(self):
await test_module.get_did_endpoint(request)

async def test_register_nym(self):
request = async_mock.MagicMock()
request.app = self.app
request.query = {"did": self.test_did, "verkey": self.test_verkey}
request = async_mock.MagicMock(
app=self.app,
query={
"did": self.test_did,
"verkey": self.test_verkey,
"role": "reset",
}
)
with async_mock.patch.object(
test_module.web, "json_response", async_mock.Mock()
) as json_response:
Expand Down
7 changes: 5 additions & 2 deletions aries_cloudagent/messaging/tests/test_valid.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import json
import pytest

from marshmallow import ValidationError
from unittest import TestCase

from marshmallow import ValidationError

from ..valid import (
BASE58_SHA256_HASH,
BASE64,
Expand Down Expand Up @@ -263,6 +265,7 @@ def test_indy_wql(self):
non_wqls = [
"nope",
"[a, b, c]",
"{1, 2, 3}",
set(),
'"Hello World"',
None,
Expand Down Expand Up @@ -363,7 +366,7 @@ def test_uuid4(self):
def test_endpoint(self):
non_endpoints = [
"123",
None,
"",
"/path/only",
"https://1.2.3.4?query=true&url=false",
"http://no_tld/bad",
Expand Down
26 changes: 1 addition & 25 deletions aries_cloudagent/messaging/valid.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import json

from datetime import datetime
from urllib.parse import urlparse

from base58 import alphabet
from marshmallow.validate import OneOf, Range, Regexp
Expand Down Expand Up @@ -265,9 +264,7 @@ def __call__(self, value):
message = "Value {input} is not a valid WQL query".format(input=value)

try:
loaded = json.loads(value)
if type(loaded) != dict:
raise ValidationError(message)
json.loads(value)
except Exception:
raise ValidationError(message)

Expand Down Expand Up @@ -386,27 +383,6 @@ def __init__(self):
Endpoint.PATTERN, error="Value {input} is not a valid endpoint",
)

def __call__(self, value):
"""Validate input value."""

super().__call__(value or "")
message = "Value {input} is not a valid endpoint".format(input=value)

try:
parsed = urlparse(value)
if (
not parsed.scheme
or not parsed.netloc
or parsed.params
or parsed.query
or parsed.fragment
):
raise ValidationError(message)
except Exception:
raise ValidationError(message)

return value


# Instances for marshmallow schema specification
INT_EPOCH = {"validate": IntEpoch(), "example": IntEpoch.EXAMPLE}
Expand Down
8 changes: 4 additions & 4 deletions aries_cloudagent/protocols/present_proof/v1_0/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class IndyProofReqSpecRestrictionsSchema(Schema):
)


class IndyProofReqNonRevoked(Schema):
class IndyProofReqNonRevokedSchema(Schema):
"""Non-revocation times specification in indy proof request."""

fro = fields.Int(
Expand Down Expand Up @@ -147,7 +147,7 @@ class IndyProofReqAttrSpecSchema(Schema):
description="If present, credential must satisfy one of given restrictions",
required=False,
)
non_revoked = fields.Nested(IndyProofReqNonRevoked(), required=False)
non_revoked = fields.Nested(IndyProofReqNonRevokedSchema(), required=False)


class IndyProofReqPredSpecSchema(Schema):
Expand All @@ -165,7 +165,7 @@ class IndyProofReqPredSpecSchema(Schema):
description="If present, credential must satisfy one of given restrictions",
required=False,
)
non_revoked = fields.Nested(IndyProofReqNonRevoked(), required=False)
non_revoked = fields.Nested(IndyProofReqNonRevokedSchema(), required=False)


class IndyProofRequestSchema(Schema):
Expand Down Expand Up @@ -196,7 +196,7 @@ class IndyProofRequestSchema(Schema):
keys=fields.Str(example="0_age_GE_uuid"), # marshmallow/apispec v3.0 ignores
values=fields.Nested(IndyProofReqPredSpecSchema()),
)
non_revoked = fields.Nested(IndyProofReqNonRevoked(), required=False)
non_revoked = fields.Nested(IndyProofReqNonRevokedSchema(), required=False)


class V10PresentationRequestRequestSchema(AdminAPIMessageTracingSchema):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ def setUp(self):
self.mock_context = async_mock.MagicMock()
self.test_instance = test_module.PresentationManager(self.mock_context)

async def test_validate_non_revoked(self):
non_revo = test_module.IndyProofReqNonRevokedSchema()
non_revo.validate({"from": 1234567890})
non_revo.validate({"to": 1234567890})
non_revo.validate({"from": 1234567890, "to": 1234567890})
with self.assertRaises(test_module.ValidationError):
non_revo.validate_fields({})

async def test_presentation_exchange_list(self):
mock = async_mock.MagicMock()
mock.query = {
Expand Down
4 changes: 2 additions & 2 deletions aries_cloudagent/revocation/routes.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"""Revocation registry admin routes."""

import logging

from asyncio import shield

from aiohttp import web
Expand All @@ -11,8 +13,6 @@
response_schema,
)

import logging

from marshmallow import fields, Schema, validate

from ..messaging.credential_definitions.util import CRED_DEF_SENT_RECORD_TYPE
Expand Down

0 comments on commit 71ad41d

Please sign in to comment.