diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py index 10b6907fc0b94135617c7812957f1efcbf0e555d..db317900a2e629a5937c8f3150b9694c1188dde6 100644 --- a/src/_zkapauthorizer/resource.py +++ b/src/_zkapauthorizer/resource.py @@ -144,9 +144,19 @@ def authorizationless_resource_tree(store, controller): b"version", _ProjectVersion(), ) + root.putChild( + b"calculate-price", + _CalculatePrice(), + ) return root +class _CalculatePrice(Resource): + """ + This resource exposes a storage price calculator. + """ + + def application_json(request): """ Set the given request's response content-type to ``application/json``. diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py index 511e015ffa24489bc8c553626843b558acd558bd..4db2af522273a16d20b7a11370013af882117721 100644 --- a/src/_zkapauthorizer/tests/test_client_resource.py +++ b/src/_zkapauthorizer/tests/test_client_resource.py @@ -106,6 +106,8 @@ from twisted.web.http import ( UNAUTHORIZED, NOT_FOUND, BAD_REQUEST, + NOT_ALLOWED, + NOT_IMPLEMENTED, ) from twisted.web.http_headers import ( Headers, @@ -1310,6 +1312,43 @@ class VoucherTests(TestCase): ) +class CalculatePriceTests(TestCase): + """ + Tests relating to ``/calculate-price`` as implemented by the + ``_zkapauthorizer.resource`` module. + """ + @given( + tahoe_configs(), + api_auth_tokens(), + sampled_from([b"GET", b"PUT", b"PATCH", b"OPTIONS", b"FOO"]), + ) + def test_wrong_method(self, get_config, api_auth_token, method): + """ + When approached with a method other than **POST** the response code is + METHOD NOT ALLOWED. + """ + config = get_config_with_api_token( + self.useFixture(TempDir()), + get_config, + api_auth_token, + ) + root = root_from_config(config, datetime.now) + agent = RequestTraversalAgent(root) + self.assertThat( + authorized_request( + api_auth_token, + agent, + method, + b"http://127.0.0.1/calculate-price", + ), + succeeded( + matches_response( + code_matcher=MatchesAny(Equals(NOT_ALLOWED), Equals(NOT_IMPLEMENTED)), + ), + ), + ) + + def application_json(): return AfterPreprocessing( lambda h: h.getRawHeaders(u"content-type"),