diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py index 873197710f6c6eaa073faba8b0b6b7b20769985d..3e6ac81ed474af990daa509578c71997aec330b5 100644 --- a/src/_zkapauthorizer/model.py +++ b/src/_zkapauthorizer/model.py @@ -308,10 +308,29 @@ class VoucherStore(object): in refs ) + @with_cursor + def insert_unblinded_tokens(self, cursor, unblinded_tokens): + """ + Store some unblinded tokens, for example as part of a backup-restore + process. + + :param list[unicode] unblinded_tokens: The unblinded tokens to store. + """ + cursor.executemany( + """ + INSERT INTO [unblinded-tokens] VALUES (?) + """, + list( + (token,) + for token + in unblinded_tokens + ), + ) + @with_cursor def insert_unblinded_tokens_for_voucher(self, cursor, voucher, public_key, unblinded_tokens): """ - Store some unblinded tokens. + Store some unblinded tokens received from redemption of a voucher. :param unicode voucher: The voucher associated with the unblinded tokens. This voucher will be marked as redeemed to indicate it diff --git a/src/_zkapauthorizer/resource.py b/src/_zkapauthorizer/resource.py index b09b58ab672e5443a062e3cc68bd6ae8dfeec8ca..1e2f5ae68ec0b3dd94113ab4ada929286df86594 100644 --- a/src/_zkapauthorizer/resource.py +++ b/src/_zkapauthorizer/resource.py @@ -27,7 +27,9 @@ from itertools import ( islice, ) from json import ( - loads, dumps, + loads, + load, + dumps, ) from zope.interface import ( Attribute, @@ -181,6 +183,16 @@ class _UnblindedTokenCollection(Resource): u"lease-maintenance-spending": self._lease_maintenance_activity(), }) + def render_POST(self, request): + """ + Store some unblinded tokens. + """ + application_json(request) + unblinded_tokens = load(request.content)[u"unblinded-tokens"] + self._store.insert_unblinded_tokens(unblinded_tokens) + return dumps({}) + + def _lease_maintenance_activity(self): activity = self._store.get_latest_lease_maintenance_activity() if activity is None: diff --git a/src/_zkapauthorizer/tests/test_client_resource.py b/src/_zkapauthorizer/tests/test_client_resource.py index 2a31085ac1151f38ddc80ebf072ff5b1a9e23038..f6d2abde71ebfdb238ce37477f4f0af4f657e926 100644 --- a/src/_zkapauthorizer/tests/test_client_resource.py +++ b/src/_zkapauthorizer/tests/test_client_resource.py @@ -343,6 +343,16 @@ class UnblindedTokenTests(TestCase): ), ) + stored_tokens = root.controller.store.backup()[u"unblinded-tokens"] + + self.assertThat( + stored_tokens, + Equals(list( + token.unblinded_token + for token + in unblinded_tokens + )), + ) @given(tahoe_configs(), vouchers(), integers(min_value=0, max_value=100)) def test_get(self, get_config, voucher, num_tokens):