In ACMEv2, challenges have "url" instead of "uri". To handle this smoothly, Challenge's uri field becomes private (_uri), and is joined by _url. Serialization and deserialization will preserve whichever one was set. The uri name is taken over by an @property that returns whichever of the two is set. I chose not to enforce that they shouldn't both be present because it would just add unnecessary code and brittleness with no stability benefit.

* Make url a virtual field.

* Add @property annotation.
This commit is contained in:
Jacob Hoffman-Andrews
2017-12-04 20:51:19 -08:00
committed by Brad Warren
parent 4db7195e77
commit 8c4f016b2d
2 changed files with 24 additions and 6 deletions
+1 -1
View File
@@ -181,7 +181,7 @@ class ClientTest(unittest.TestCase):
# TODO: split here and separate test
self.assertRaises(errors.UnexpectedUpdate, self.client.answer_challenge,
self.challr.body.update(uri='foo'), chall_response)
self.challr.body.update(_uri='foo'), chall_response)
def test_answer_challenge_missing_next(self):
self.assertRaises(
+23 -5
View File
@@ -325,13 +325,26 @@ class ChallengeBody(ResourceBody):
"""
__slots__ = ('chall',)
uri = jose.Field('uri')
# ACMEv1 has a "uri" field in challenges. ACMEv2 has a "url" field. This
# challenge object supports either one. In Client.answer_challenge,
# whichever one is set will be used.
_uri = jose.Field('uri', omitempty=True, default=None)
_url = jose.Field('url', omitempty=True, default=None)
status = jose.Field('status', decoder=Status.from_json,
omitempty=True, default=STATUS_PENDING)
validated = fields.RFC3339Field('validated', omitempty=True)
error = jose.Field('error', decoder=Error.from_json,
omitempty=True, default=None)
def __init__(self, **kwargs):
new_kwargs = {}
for k, v in kwargs.items():
if k in ('uri', 'url',):
k = '_' + k
new_kwargs[k] = v
# pylint: disable=star-args
super(ChallengeBody, self).__init__(**new_kwargs)
def to_partial_json(self):
jobj = super(ChallengeBody, self).to_partial_json()
jobj.update(self.chall.to_partial_json())
@@ -343,6 +356,11 @@ class ChallengeBody(ResourceBody):
jobj_fields['chall'] = challenges.Challenge.from_json(jobj)
return jobj_fields
@property
def uri(self):
"""The URL of this challenge."""
return self._url or self._uri
def __getattr__(self, name):
return getattr(self.chall, name)
@@ -358,10 +376,10 @@ class ChallengeResource(Resource):
authzr_uri = jose.Field('authzr_uri')
@property
def uri(self): # pylint: disable=missing-docstring,no-self-argument
# bug? 'method already defined line None'
# pylint: disable=function-redefined
return self.body.uri # pylint: disable=no-member
def uri(self):
"""The URL of the challenge body."""
# pylint: disable=function-redefined,no-member
return self.body.uri
class Authorization(ResourceBody):