From 7a95bd179b058f5667a587a862da35e67d2f202e Mon Sep 17 00:00:00 2001 From: Jean-Paul Calderone <exarkun@twistedmatrix.com> Date: Wed, 13 Nov 2019 11:43:11 -0500 Subject: [PATCH] Add a redeemed `token-count` to the voucher model --- src/_zkapauthorizer/model.py | 24 ++++++++++---- src/_zkapauthorizer/tests/test_model.py | 44 ++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/_zkapauthorizer/model.py b/src/_zkapauthorizer/model.py index 8fd2e8f..c8d2a32 100644 --- a/src/_zkapauthorizer/model.py +++ b/src/_zkapauthorizer/model.py @@ -122,8 +122,10 @@ def open_and_initialize(path, required_schema_version, connect=None): """ CREATE TABLE IF NOT EXISTS [vouchers] ( [number] text, - [created] text, -- An ISO8601 date+time string. - [redeemed] num DEFAULT 0, + [created] text, -- An ISO8601 date+time string. + [redeemed] num DEFAULT 0, -- 0 if the voucher has not been redeemed, 1 otherwise. + [token-count] num DEFAULT NULL, -- NULL if the voucher has not been redeemed, + -- a number of tokens received on its redemption otherwise. PRIMARY KEY([number]) ) @@ -219,7 +221,7 @@ class VoucherStore(object): cursor.execute( """ SELECT - [number], [created], [redeemed] + [number], [created], [redeemed], [token-count] FROM [vouchers] WHERE @@ -277,7 +279,7 @@ class VoucherStore(object): """ cursor.execute( """ - SELECT [number], [created], [redeemed] FROM [vouchers] + SELECT [number], [created], [redeemed], [token-count] FROM [vouchers] """, ) refs = cursor.fetchall() @@ -312,9 +314,12 @@ class VoucherStore(object): ) cursor.execute( """ - UPDATE [vouchers] SET [redeemed] = 1 WHERE [number] = ? + UPDATE [vouchers] + SET [redeemed] = 1 + , [token-count] = ? + WHERE [number] = ? """, - (voucher,), + (len(unblinded_tokens), voucher), ) @with_cursor @@ -422,14 +427,18 @@ class Voucher(object): :ivar bool redeemed: ``True`` if this voucher has successfully been redeemed with a payment server, ``False`` otherwise. + + :ivar int token_count: A number of tokens received from the redemption of + this voucher if it has been redeemed, ``None`` if it has not been + redeemed. """ number = attr.ib() created = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(datetime))) redeemed = attr.ib(default=False, validator=attr.validators.instance_of(bool)) + token_count = attr.ib(default=None, validator=attr.validators.optional(attr.validators.instance_of(int))) @classmethod def from_row(cls, row): - print(row[1]) return cls( row[0], # All Python datetime-based date/time libraries fail to handle @@ -439,6 +448,7 @@ class Voucher(object): # represent a leap second... I hope. parse_datetime(row[1], delimiter=u" "), bool(row[2]), + row[3], ) @classmethod diff --git a/src/_zkapauthorizer/tests/test_model.py b/src/_zkapauthorizer/tests/test_model.py index 319b363..f53bd5b 100644 --- a/src/_zkapauthorizer/tests/test_model.py +++ b/src/_zkapauthorizer/tests/test_model.py @@ -48,9 +48,12 @@ from fixtures import ( from hypothesis import ( given, ) + from hypothesis.strategies import ( + data, lists, datetimes, + integers, ) from twisted.python.filepath import ( @@ -155,6 +158,8 @@ class VoucherStoreTests(TestCase): MatchesStructure( number=Equals(voucher), created=Equals(now), + redeemed=Equals(False), + token_count=Equals(None), ), ) @@ -292,12 +297,35 @@ class UnblindedTokenStoreTests(TestCase): more_unblinded_tokens = store.extract_unblinded_tokens(1) self.expectThat([], Equals(more_unblinded_tokens)) - @given(tahoe_configs(), datetimes(), vouchers(), random_tokens(), unblinded_tokens()) - def test_mark_vouchers_redeemed(self, get_config, now, voucher_value, token, one_token): + @given( + tahoe_configs(), + datetimes(), + vouchers(), + integers(min_value=1, max_value=100), + data(), + ) + def test_mark_vouchers_redeemed(self, get_config, now, voucher_value, num_tokens, data): """ The voucher for unblinded tokens that are added to the store is marked as redeemed. """ + random = data.draw( + lists( + random_tokens(), + min_size=num_tokens, + max_size=num_tokens, + unique=True, + ), + ) + unblinded = data.draw( + lists( + unblinded_tokens(), + min_size=num_tokens, + max_size=num_tokens, + unique=True, + ), + ) + tempdir = self.useFixture(TempDir()) config = get_config(tempdir.join(b"node"), b"tub.port") store = VoucherStore.from_node_config( @@ -305,7 +333,13 @@ class UnblindedTokenStoreTests(TestCase): lambda: now, memory_connect, ) - store.add(voucher_value, [token]) - store.insert_unblinded_tokens_for_voucher(voucher_value, [one_token]) + store.add(voucher_value, random) + store.insert_unblinded_tokens_for_voucher(voucher_value, unblinded) loaded_voucher = store.get(voucher_value) - self.assertThat(loaded_voucher.redeemed, Equals(True)) + self.assertThat( + loaded_voucher, + MatchesStructure( + redeemed=Equals(True), + token_count=Equals(num_tokens), + ), + ) -- GitLab