Skip to content

Commit c08f61c

Browse files
author
Brad Porter
authored
Merge pull request #99 from iovation/3.7-DEV
3.7 dev to master
2 parents aa2caed + 7f0414d commit c08f61c

File tree

12 files changed

+105
-14
lines changed

12 files changed

+105
-14
lines changed

CHANGES.rst

+6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
CHANGELOG for LaunchKey Python SDK
22
==================================
33

4+
3.7.0
5+
-----
6+
7+
* Add device ID list to `AuthorizationRequest` object
8+
* Update CLI to display device ID list upon authorization request
9+
410
3.6.0
511
-----
612

examples/cli/cli.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ def authorize(ctx, service_id, username, context, title, ttl, push_title,
133133
"Authorization request successful",
134134
{
135135
"Auth Request": auth.auth_request,
136-
"Push Package": auth.push_package
136+
"Push Package": auth.push_package,
137+
"Device IDs": auth.device_ids
137138
},
138139
color=SUCCESS_COLOR
139140
)

features/service_client/auth_request/service-client-auth-request-send.feature

+7
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Feature: Service Client Authorization Request: Can Send Request
88

99
Background:
1010
Given I created a Directory
11+
And I have added an SDK Key to the Directory
1112
And I created a Directory Service
1213

1314
Scenario: Making a request with a valid User an no linked Devices raises EntityNotFound
@@ -22,3 +23,9 @@ Feature: Service Client Authorization Request: Can Send Request
2223
Scenario: Making a request including context with an invalid User Throws EntityNotFound
2324
When I attempt to make an Authorization request with the context value "Hello iovation!"
2425
Then a EntityNotFound error occurs
26+
27+
@device_testing
28+
Scenario: Making a request with a valid user device parses the device IDs in the response
29+
Given I have a linked Device
30+
When I make an Authorization request
31+
Then the Authorization Request response Device IDs matches the current Devices list

features/steps/managers/directory_service_auths.py

+12-4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class DirectoryServiceAuthsManager(BaseManager):
1313
def __init__(self, organization_factory):
1414
self.current_auth_response = None
1515
self.previous_auth_response = None
16+
self.current_auth_request = None
1617
self.current_auth_request_id = None
1718
self.previous_auth_request_id = None
1819
super(DirectoryServiceAuthsManager, self, ).__init__(
@@ -43,7 +44,7 @@ def create_auth_request(self, service_id, user, context=None, policy=None,
4344
push_body=None, denial_reasons=None):
4445
client = self._get_service_client(service_id)
4546
try:
46-
self.current_auth_request_id = client.authorization_request(
47+
current_auth_request = client.authorization_request(
4748
user,
4849
context=context,
4950
policy=policy,
@@ -52,10 +53,14 @@ def create_auth_request(self, service_id, user, context=None, policy=None,
5253
push_title=push_title,
5354
push_body=push_body,
5455
denial_reasons=denial_reasons
55-
).auth_request
56+
)
57+
58+
self.current_auth_request = current_auth_request
59+
self.current_auth_request_id = current_auth_request.auth_request
60+
5661
except EntityNotFound:
5762
sleep(2)
58-
self.current_auth_request_id = client.authorization_request(
63+
current_auth_request = client.authorization_request(
5964
user,
6065
context=context,
6166
policy=policy,
@@ -64,7 +69,10 @@ def create_auth_request(self, service_id, user, context=None, policy=None,
6469
push_title=push_title,
6570
push_body=push_body,
6671
denial_reasons=denial_reasons
67-
).auth_request
72+
)
73+
74+
self.current_auth_request = current_auth_request
75+
self.current_auth_request_id = current_auth_request.auth_request
6876

6977
def get_auth_response(self, service_id, auth_request):
7078
client = self._get_service_client(service_id)

features/steps/service_auth_steps.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from behave import given, when, then
22

3+
from hamcrest import assert_that, equal_to
4+
35
from launchkey.entities.service import GeoFence, AuthMethod, AuthMethodType, \
46
Requirement, AuthResponseReason
57

@@ -263,4 +265,29 @@ def parse_input(value):
263265
"is not supported on all devices, so this may fail." %
264266
(expected_method, methods[i], expected_method.method))
265267
else:
266-
raise Exception("Expected %s but got %s" % (expected_method, methods[i]))
268+
raise Exception("Expected %s but got %s" % (expected_method,
269+
methods[i]))
270+
271+
272+
@then("the Authorization Request response Device IDs matches the current "
273+
"Devices list")
274+
def verify_device_ids_match_device_list(context):
275+
request = context.directory_service_auths_manager.current_auth_request
276+
277+
if not request:
278+
raise Exception("Expected an auth request to be present but got none.")
279+
280+
request_device_ids = request.device_ids
281+
282+
if not request_device_ids:
283+
raise Exception("Expected device IDs to be present in auth request "
284+
"but got %s instead." % request_device_ids)
285+
286+
current_directory = context.entity_manager.get_current_directory()
287+
current_user_identifier = context.directory_device_manager. \
288+
current_user_identifier
289+
current_user_devices = context.directory_device_manager \
290+
.retrieve_user_devices(current_user_identifier, current_directory.id)
291+
current_user_device_ids = [d.id for d in current_user_devices]
292+
293+
assert_that(request_device_ids, equal_to(current_user_device_ids))

launchkey/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""LaunchKey Service SDK module"""
2-
SDK_VERSION = '3.6.0'
2+
SDK_VERSION = '3.7.0'
33
LAUNCHKEY_PRODUCTION = "https://api.launchkey.com"
44
VALID_JWT_ISSUER_LIST = ["svc", "dir", "org"]
55
JOSE_SUPPORTED_JWE_ALGS = ['RSA-OAEP']

launchkey/clients/service.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ def authorization_request(self, user, context=None, policy=None,
171171
self._subject, **kwargs)
172172
data = self._validate_response(response, AuthorizeValidator)
173173
return AuthorizationRequest(data.get('auth_request'),
174-
data.get('push_package'))
174+
data.get('push_package'),
175+
data.get('device_ids'))
175176

176177
@api_call
177178
def get_advanced_authorization_response(self, authorization_request_id):

launchkey/entities/service/__init__.py

+7-4
Original file line numberDiff line numberDiff line change
@@ -479,21 +479,24 @@ def __repr__(self):
479479

480480
class AuthorizationRequest(object):
481481
"""
482-
Authorization Response object containing decrypted auth response
482+
Authorization Request object containing decrypted auth response
483483
and other related information
484484
"""
485485

486-
def __init__(self, auth_request, push_package):
486+
def __init__(self, auth_request, push_package, device_ids=None):
487487
self.auth_request = auth_request
488488
self.push_package = push_package
489+
self.device_ids = device_ids
489490

490491
def __repr__(self):
491492
return "AuthorizationRequest <" \
492493
"auth_request=\"{auth_request}\", " \
493-
"push_package=\"{push_package}\">".\
494+
"push_package=\"{push_package}\", " \
495+
"device_ids=\"{device_ids}\">".\
494496
format(
495497
auth_request=self.auth_request,
496-
push_package=self.push_package
498+
push_package=self.push_package,
499+
device_ids=self.device_ids
497500
)
498501

499502

launchkey/entities/validation.py

+1
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ class AuthorizeValidator(Schema):
270270
"""Authorize entity validator"""
271271
auth_request = validators.String(not_empty=True)
272272
push_package = validators.String(if_missing=None, not_empty=True)
273+
device_ids = ForEach(validators.String(), if_missing=None)
273274
allow_extra_fields = True
274275

275276

tests/test_entities_service.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import unittest
22

33
import json
4+
from uuid import uuid4
5+
46
from mock import MagicMock, patch
57
from ddt import data, unpack, ddt
68
from formencode import Invalid
@@ -1583,7 +1585,21 @@ def test_repr(self):
15831585
self.assertEqual(
15841586
str(auth_request),
15851587
'AuthorizationRequest <auth_request="auth", '
1586-
'push_package="package">'
1588+
'push_package="package", '
1589+
'device_ids="None">'
1590+
)
1591+
1592+
faux_device_id = str(uuid4())
1593+
auth_request_with_device_ids = AuthorizationRequest(
1594+
auth_request='auth',
1595+
push_package='package',
1596+
device_ids=[faux_device_id])
1597+
1598+
self.assertEqual(
1599+
str(auth_request_with_device_ids),
1600+
'AuthorizationRequest <auth_request="auth", '
1601+
'push_package="package", '
1602+
'device_ids="[\'%s\']">' % faux_device_id
15871603
)
15881604

15891605

tests/test_service_client.py

+12
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ def test_authorization_request_response_has_push_package(self):
8383
self._response.data = {"auth_request": "auth", "push_package": "expected package"}
8484
self.assertEqual('expected package', self._service_client.authorization_request(ANY).push_package)
8585

86+
def test_authorization_request_response_has_device_ids(self):
87+
expected_device_ids = ["expected_device_id"]
88+
self._response.data = {
89+
"auth_request": "auth",
90+
"push_package": "expected package",
91+
"device_ids": expected_device_ids
92+
}
93+
94+
self.assertEqual(
95+
expected_device_ids,
96+
self._service_client.authorization_request(ANY).device_ids)
97+
8698
def test_authorization_request_invalid_policy_input(self):
8799
self._response.data = {"auth_request": ANY}
88100
with self.assertRaises(InvalidParameters):

tests/test_validation.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@
1515
class TestAuthorizeValidator(TestCase):
1616

1717
def setUp(self):
18+
self._expected_device_ids = ['expected_device_id']
1819
self._data = {
1920
'auth_request': 'Expected Auth Request',
20-
'push_package': 'Expected Push Package'
21+
'push_package': 'Expected Push Package',
22+
'device_ids': self._expected_device_ids
2123
}
2224
self._validator = AuthorizeValidator()
2325

@@ -62,6 +64,13 @@ def test_push_package_returns_unchanged_string(self):
6264
actual = self._validator.to_python(self._data)
6365
self.assertIn('push_package', actual)
6466
self.assertEqual(actual['push_package'], expected)
67+
self.assertEqual(actual["device_ids"], self._expected_device_ids)
68+
69+
def test_device_ids_may_be_missing(self):
70+
del self._data["device_ids"]
71+
actual = self._validator.to_python(self._data)
72+
self.assertIn('device_ids', actual)
73+
self.assertIsNone(actual['device_ids'])
6574

6675

6776
@ddt

0 commit comments

Comments
 (0)