diff --git a/src/_secureaccesstokenauthorizer/_storage_server.py b/src/_secureaccesstokenauthorizer/_storage_server.py index 79585222ff7af9274791eb260f820749f21b9b24..2e1501aa5eebafaa712fd21bd269da1d06574073 100644 --- a/src/_secureaccesstokenauthorizer/_storage_server.py +++ b/src/_secureaccesstokenauthorizer/_storage_server.py @@ -18,7 +18,7 @@ updates using a per-call token. """ from zope.interface import ( - implementer, + implementer_only, ) from twisted.python.components import ( @@ -32,6 +32,10 @@ from foolscap.api import ( ListOf, Referenceable, ) +from foolscap.ipb import ( + IReferenceable, + IRemotelyCallable, +) from foolscap.remoteinterface import ( RemoteMethodSchema, RemoteInterface, @@ -95,7 +99,7 @@ class RITokenAuthorizedStorageServer(RemoteInterface): -@implementer(RITokenAuthorizedStorageServer) +@implementer_only(RITokenAuthorizedStorageServer, IReferenceable, IRemotelyCallable) class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer), Referenceable): def allocate_buckets(self, tokens, *a, **kw): self._validate_tokens(tokens) @@ -104,3 +108,17 @@ class SecureAccessTokenAuthorizerStorageServer(proxyForInterface(RIStorageServer def add_lease(self, tokens, *a, **kw): self._validate_tokens(tokens) return super(SecureAccessTokenAuthorizerStorageServer, self).add_lease(*a, **kw) + +# I don't understand why this is required. +# SecureAccessTokenAuthorizerStorageServer is-a Referenceable. It seems like +# the built in adapter should take care of this case. +from twisted.python.components import ( + registerAdapter, +) +from foolscap.referenceable import ( + ReferenceableSlicer, +) +from foolscap.ipb import ( + ISlicer, +) +registerAdapter(ReferenceableSlicer, SecureAccessTokenAuthorizerStorageServer, ISlicer) diff --git a/src/_secureaccesstokenauthorizer/tests/test_plugin.py b/src/_secureaccesstokenauthorizer/tests/test_plugin.py index d57d304cb80a57490d9779a9eafe0af6c41252dd..ef1827dc3223177c15f43096f44c553d4ceab876 100644 --- a/src/_secureaccesstokenauthorizer/tests/test_plugin.py +++ b/src/_secureaccesstokenauthorizer/tests/test_plugin.py @@ -24,6 +24,7 @@ from testtools import ( TestCase, ) from testtools.matchers import ( + Always, Contains, AfterPreprocessing, ) @@ -35,6 +36,9 @@ from hypothesis import ( given, ) +from foolscap.broker import ( + Broker, +) from foolscap.ipb import ( IReferenceable, IRemotelyCallable, @@ -48,6 +52,9 @@ from allmydata.interfaces import ( from twisted.plugin import ( getPlugins, ) +from twisted.test.proto_helpers import ( + StringTransport, +) from twisted.plugins.secureaccesstokenauthorizer import ( storage_server, ) @@ -107,10 +114,6 @@ class PluginTests(TestCase): ``storage_server.get_storage_server`` provides ``IReferenceable`` and ``IRemotelyCallable``. """ - # XXX It's not clear what the actual Foolscap-imposed requirements on - # this object should be. Maybe the two above-mentioned interfaces are - # important ... or maybe not? - storage_server_deferred = storage_server.get_storage_server( configuration, get_anonymous_storage_server, @@ -124,3 +127,26 @@ class PluginTests(TestCase): ), ), ) + + @given(configurations()) + def test_returns_serializable(self, configuration): + """ + The storage server attached to the result of + ``storage_server.get_storage_server`` can be serialized by a banana + Broker (for Foolscap). + """ + storage_server_deferred = storage_server.get_storage_server( + configuration, + get_anonymous_storage_server, + ) + broker = Broker(None) + broker.makeConnection(StringTransport()) + self.expectThat( + storage_server_deferred, + succeeded( + AfterPreprocessing( + lambda ann: broker.send(ann.storage_server), + Always(), + ), + ), + )