Skip to content

Commit 828a8e8

Browse files
committed
Add internal refreshJson method to Bidstream client
1 parent d4bcab5 commit 828a8e8

File tree

7 files changed

+169
-75
lines changed

7 files changed

+169
-75
lines changed

tests/test_bidstream_client.py

Lines changed: 107 additions & 60 deletions
Large diffs are not rendered by default.

tests/test_refresh_keys_util.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ def test_parse_keys_json_identity(self):
8585
response_body['max_bidstream_lifetime_seconds'] = '100'
8686
response_body['max_sharing_lifetime_seconds'] = '200'
8787
response_body['allow_clock_skew_seconds'] = '300'
88-
keys = refresh_keys_util.parse_keys_json(response_body)
88+
refresh_response = refresh_keys_util.parse_keys_json(response_body)
89+
self.assertTrue(refresh_response.success)
90+
keys = refresh_response.keys
8991
self.assertIsNotNone(keys)
9092
self.assertEqual(IdentityScope.EUID, keys.get_identity_scope())
9193
self.assertEqual('1', keys.get_caller_site_id())

tests/test_sharing_client.py

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,38 @@ def setUp(self):
1616
self._key_collection = create_key_collection(IdentityScope.UID2)
1717
self._client = SharingClient(self._CONST_BASE_URL, self._CONST_API_KEY, client_secret)
1818

19+
def _assert_success(self, decryption_response, token_version, scope):
20+
self.assertTrue(decryption_response.success)
21+
self.assertEqual(decryption_response.uid, example_uid)
22+
self.assertEqual(decryption_response.advertising_token_version, token_version)
23+
if (token_version == AdvertisingTokenVersion.ADVERTISING_TOKEN_V3
24+
or token_version == AdvertisingTokenVersion.ADVERTISING_TOKEN_V4):
25+
self.assertEqual(decryption_response.identity_type, IdentityType.Email)
26+
else:
27+
self.assertEqual(decryption_response.identity_type, None)
28+
self.assertEqual(decryption_response.identity_scope, scope)
29+
self.assertEqual(decryption_response.is_client_side_generated, False)
30+
31+
def _assert_fails(self, decryption_response, token_version, scope):
32+
self.assertFalse(decryption_response.success)
33+
self.assertEqual(decryption_response.status, DecryptionStatus.INVALID_TOKEN_LIFETIME)
34+
self.assertEqual(decryption_response.advertising_token_version, token_version)
35+
self.assertEqual(decryption_response.identity_scope, scope)
36+
if (token_version == AdvertisingTokenVersion.ADVERTISING_TOKEN_V3
37+
or token_version == AdvertisingTokenVersion.ADVERTISING_TOKEN_V4):
38+
self.assertEqual(decryption_response.identity_type, IdentityType.Email)
39+
40+
def decrypt_and_assert_success(self, token, token_version, scope):
41+
decrypted = self._client.decrypt_token_into_raw_uid(token)
42+
self._assert_success(decrypted, token_version, scope)
43+
1944
def test_smoke_test(self, mock_refresh_sharing_keys): # SmokeTest
2045
for expected_scope, expected_version in test_cases_all_scopes_all_versions:
2146
with self.subTest(expected_scope=expected_scope, expected_version=expected_version):
2247
token = generate_uid_token(expected_scope, expected_version)
2348
mock_refresh_sharing_keys.return_value = RefreshResponse.make_success(create_key_collection(expected_scope))
2449
self._client.refresh()
25-
decrypted = self._client.decrypt_token_into_raw_uid(token)
26-
self.assertEqual(decrypted.identity_scope, expected_scope)
27-
self.assertEqual(decrypted.advertising_token_version, expected_version)
28-
self.assertEqual((now - decrypted.established).total_seconds(), 0)
50+
self.decrypt_and_assert_success(token, expected_version, expected_scope)
2951

3052
def test_token_lifetime_too_long_for_sharing(self, mock_refresh_sharing_keys): # TokenLifetimeTooLongForSharing
3153
expires_in_sec = dt.datetime.now(tz=timezone.utc) + dt.timedelta(days=31)
@@ -38,8 +60,7 @@ def test_token_lifetime_too_long_for_sharing(self, mock_refresh_sharing_keys):
3860
99999, 86400, max_sharing_lifetime))
3961
self._client.refresh()
4062
result = self._client.decrypt_token_into_raw_uid(token)
41-
self.assertFalse(result.success)
42-
self.assertEqual(DecryptionStatus.INVALID_TOKEN_LIFETIME, result.status)
63+
self._assert_fails(result, expected_version, expected_scope)
4364

4465
def test_token_generated_in_the_future_to_simulate_clock_skew(self, mock_refresh_sharing_keys): # TokenGeneratedInTheFutureToSimulateClockSkew
4566
created_at_future = dt.datetime.now(tz=timezone.utc) + dt.timedelta(minutes=31) #max allowed clock skew is 30m
@@ -51,8 +72,7 @@ def test_token_generated_in_the_future_to_simulate_clock_skew(self, mock_refresh
5172
99999, 86400))
5273
self._client.refresh()
5374
result = self._client.decrypt_token_into_raw_uid(token)
54-
self.assertFalse(result.success)
55-
self.assertEqual(DecryptionStatus.INVALID_TOKEN_LIFETIME, result.status)
75+
self._assert_fails(result, expected_version, expected_scope)
5676

5777
def test_token_generated_in_the_future_within_allowed_clock_skew(self, mock_refresh_sharing_keys): # TokenGeneratedInTheFutureWithinAllowedClockSkew
5878
created_at_future = dt.datetime.now(tz=timezone.utc) + dt.timedelta(minutes=29) #max allowed clock skew is 30m

tests/test_utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,12 @@
6060
IN_2_DAYS = now + dt.timedelta(days=2)
6161
IN_3_DAYS = now + dt.timedelta(days=3)
6262

63+
6364
def get_identity_type(token):
6465
first_char = token[0]
65-
if ('A' == first_char or 'E' == first_char):
66+
if 'A' == first_char or 'E' == first_char:
6667
return IdentityType.Email
67-
if ('F' == first_char or 'B' == first_char):
68+
if 'F' == first_char or 'B' == first_char:
6869
return IdentityType.Phone
6970

7071
raise Exception("unknown IdentityType")
@@ -110,6 +111,7 @@ def format_key(key: EncryptionKey):
110111
base64.b64encode(key.secret).decode("utf-8"))
111112

112113

114+
113115
def create_default_key_collection(key_set):
114116
return EncryptionKeysCollection(key_set, IdentityScope.UID2, 9000, 1,
115117
99999, 2)

uid2_client/bid_stream_client.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
"""
44
import base64
55
import datetime as dt
6+
import json
67

78
from .client_type import ClientType
89
from .encryption import decrypt_token
9-
from .refresh_keys_util import refresh_bidstream_keys
10+
from .refresh_keys_util import refresh_bidstream_keys, parse_keys_json
1011

1112

1213
class BidstreamClient:
@@ -70,3 +71,11 @@ def refresh(self):
7071
self._keys = refresh_response.keys
7172

7273
return refresh_response
74+
75+
def _refresh_json(self, json_str):
76+
body = json.loads(json_str)
77+
refresh_response = parse_keys_json(body['body'])
78+
if refresh_response.success:
79+
self._keys = refresh_response.keys
80+
81+
return refresh_response

uid2_client/client.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,12 @@ def refresh_keys(self):
8686

8787
def refresh_json(self, json_str):
8888
body = json.loads(json_str)
89-
return parse_keys_json(body['body'])
89+
refresh_response = parse_keys_json(body['body'])
90+
if refresh_response.success:
91+
self._keys = refresh_response.keys
92+
return refresh_response.keys
93+
else:
94+
raise Exception(refresh_response.reason)
9095

9196
def encrypt(self, uid2, keyset_id=None):
9297
""" Encrypt an UID2 into a sharing token
@@ -118,5 +123,6 @@ def decrypt(self, token):
118123
"""
119124
return decrypt(token, self._keys)
120125

126+
121127
class Uid2ClientError(Exception):
122128
"""Raised for problems encountered while interacting with UID2 services."""

uid2_client/refresh_keys_util.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def _make_dt(timestamp):
1212
return dt.datetime.fromtimestamp(timestamp, tz=timezone.utc)
1313

1414

15-
def parse_keys_json(resp_body):
15+
def _parse_keys_json(resp_body):
1616
keys = []
1717
identity_scope = IdentityScope.UID2
1818
if resp_body["identity_scope"] == "EUID":
@@ -39,7 +39,15 @@ def _fetch_keys(base_url, path, auth_key, secret_key):
3939
req, nonce = make_v2_request(secret_key, dt.datetime.now(tz=timezone.utc))
4040
resp = post(base_url, path, headers=auth_headers(auth_key), data=req)
4141
resp_body = json.loads(parse_v2_response(secret_key, resp.read(), nonce)).get('body')
42-
keys = parse_keys_json(resp_body)
42+
keys = _parse_keys_json(resp_body)
43+
return RefreshResponse.make_success(keys)
44+
except Exception as exc:
45+
return RefreshResponse.make_error(exc.args)
46+
47+
48+
def parse_keys_json(resp_body):
49+
try:
50+
keys = _parse_keys_json(resp_body)
4351
return RefreshResponse.make_success(keys)
4452
except Exception as exc:
4553
return RefreshResponse.make_error(exc.args)

0 commit comments

Comments
 (0)