Skip to content

Commit aa2caed

Browse files
Brad Porterlordkyzr
Brad Porter
authored andcommitted
3.6.0 Release (#92)
* Bug fix to ensure that requests do not follow redirects * Bug fix to ensure that public key is cached using `kid` header of JWT found within a response header * Added Policies: ConditionalGeofence, MethodAmount, Factors, Legacy * Added Requirement enum * enum34 only required on python versions < 3.4 * Deprecated: TimeFence * Deprecated: `ServiceSecurityPolicy` * Deprecated: `get_service_policy` method on `ServiceManagingBaseClient` class * Deprecated: `set_service_policy` method on `ServiceManagingBaseClient` class * Deprecated: `get_authorization_response` method on `ServiceClient` class * Deprecated: `handle_webhook` method on `ServiceClient` class * Added: `get_advanced_service_policy` method on `ServiceManagingBaseClient` class * Added: `set_advanced_service_policy` method on `ServiceManagingBaseClient` class * Added: `get_advanced_authorization_response` method on `ServiceClient` class * Added: `handle_advanced_webhook` method on `ServiceClient` class * Added: `AdvancedAuthorizationResponse` class * Added: `AuthorizationResponsePolicy` class
1 parent 7bed012 commit aa2caed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+4536
-218
lines changed

CHANGES.rst

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

4+
3.6.0
5+
-----
6+
7+
* Bug fix to ensure that requests do not follow redirects
8+
* Bug fix to ensure that public key is cached using `kid` header of JWT found within a response header
9+
* Added Policies: ConditionalGeofence, MethodAmount, Factors, Legacy
10+
* Added Requirement enum
11+
* enum34 only required on python versions < 3.4
12+
* Deprecated: TimeFence
13+
* Deprecated: `ServiceSecurityPolicy`
14+
* Deprecated: `get_service_policy` method on `ServiceManagingBaseClient` class
15+
* Deprecated: `set_service_policy` method on `ServiceManagingBaseClient` class
16+
* Deprecated: `get_authorization_response` method on `ServiceClient` class
17+
* Deprecated: `handle_webhook` method on `ServiceClient` class
18+
* Added: `get_advanced_service_policy` method on `ServiceManagingBaseClient` class
19+
* Added: `set_advanced_service_policy` method on `ServiceManagingBaseClient` class
20+
* Added: `get_advanced_authorization_response` method on `ServiceClient` class
21+
* Added: `handle_advanced_webhook` method on `ServiceClient` class
22+
* Added: `AdvancedAuthorizationResponse` class
23+
* Added: `AuthorizationResponsePolicy` class
24+
425
3.5.0
526
-----
627

README.rst

+9-5
Original file line numberDiff line numberDiff line change
@@ -253,9 +253,13 @@ Contributing
253253

254254
1. Fork it
255255
2. Create your feature branch (`git checkout -b my-new-feature`)
256-
3. Verify your code passes unit tests (`python setup.py test`)
257-
4. Verify your code passes tests, linting, and PEP-8 on all supported python
256+
3. Conform to the following standards:
257+
* PEP-8
258+
* Relative imports for same level or submodules
259+
260+
4. Verify your code passes unit tests (`python setup.py test`)
261+
5. Verify your code passes tests, linting, and PEP-8 on all supported python
258262
versions (`tox`)
259-
5. Commit your changes (`git commit -am 'Add some feature'`)
260-
6. Push to the branch (`git push origin my-new-feature`)
261-
7. Create new Pull Request
263+
6. Commit your changes (`git commit -am 'Add some feature'`)
264+
7. Push to the branch (`git push origin my-new-feature`)
265+
8. Create new Pull Request

examples/cli/cli.py

+16-5
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,15 @@ def main(ctx, entity_type, entity_id, private_key, api):
8282
help="How many custom denial reasons to include. "
8383
"If this is not included default denial reasons are used.",
8484
type=click.IntRange(min=2))
85+
@click.option('--use-advanced',
86+
is_flag=True,
87+
default=False,
88+
help="Whether to retrieve the Advanced Authorization Response "
89+
"or the old Authorization Response",
90+
type=click.BOOL)
8591
@click.pass_context
8692
def authorize(ctx, service_id, username, context, title, ttl, push_title,
87-
push_body, denial_reason_count):
93+
push_body, denial_reason_count, use_advanced):
8894
"""SERVICE_ID USERNAME"""
8995
client = get_service_client(service_id, ctx.obj['factory'])
9096

@@ -146,9 +152,14 @@ def authorize(ctx, service_id, username, context, title, ttl, push_title,
146152
click.echo("Checking for response from user.")
147153

148154
try:
149-
auth_response = wait_for_response(
150-
client.get_authorization_response, [auth.auth_request]
151-
)
155+
if use_advanced:
156+
auth_response = wait_for_response(
157+
client.get_advanced_authorization_response, [auth.auth_request]
158+
)
159+
else:
160+
auth_response = wait_for_response(
161+
client.get_authorization_response, [auth.auth_request]
162+
)
152163

153164
if auth_response.authorized:
154165
message = "Authorization request approved by user."
@@ -173,7 +184,7 @@ def authorize(ctx, service_id, username, context, title, ttl, push_title,
173184
"User Push ID": auth_response.user_push_id,
174185
"Org User Hash": auth_response.organization_user_hash,
175186
"Auth Methods": auth_response.auth_methods,
176-
"Auth Policy": auth_response.auth_policy
187+
"Auth Policy": auth_response.policy if use_advanced else auth_response.auth_policy
177188
},
178189
color=color
179190
)

examples/flask-webhooks-example/instance/example_config.py

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
ORGANIZATION_KEY = open("/path/to/private.key").read()
1010
DIRECTORY_ID = "e243bf77-9966-4fbd-90ed-bb7f4405d9cf"
1111
SERVICE_ID = "babdb1b5-cb52-4231-9e72-c72732a47c00"
12+
USE_ADVANCED_WEBHOOKS = True

examples/flask-webhooks-example/launchkey_example_app/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ def setup_logging():
2525
app.config['ORGANIZATION_KEY'],
2626
app.config['DIRECTORY_ID'],
2727
app.config['SERVICE_ID'],
28-
app.config.get('LAUNCHKEY_API', LAUNCHKEY_PRODUCTION)
28+
app.config.get('LAUNCHKEY_API', LAUNCHKEY_PRODUCTION),
29+
app.config.get("USE_ADVANCED_WEBHOOKS", False)
2930
)
3031

3132
launchkey_service.update_directory_webhook_url(

examples/flask-webhooks-example/launchkey_example_app/services/launchkey_service.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
class LaunchKeyService:
55
def __init__(self, organization_id, organization_key, directory_id,
6-
service_id, launchkey_url):
6+
service_id, launchkey_url, use_advanced_webhooks):
77
self.organization_id = organization_id
88
self.directory_id = directory_id
99
self.service_id = service_id
@@ -22,6 +22,8 @@ def __init__(self, organization_id, organization_key, directory_id,
2222
service_id
2323
)
2424

25+
self.use_advanced_webhooks = use_advanced_webhooks
26+
2527
def update_directory_webhook_url(self, webhook_url):
2628
self.organization_client.update_directory(
2729
self.directory_id,
@@ -54,7 +56,10 @@ def session_end(self, username):
5456
self.service_client.session_end(username)
5557

5658
def handle_service_webhook(self, body, headers, method, path):
57-
return self.service_client.handle_webhook(body, headers, method, path)
59+
if self.use_advanced_webhooks:
60+
return self.service_client.handle_advanced_webhook(body, headers, method, path)
61+
else:
62+
return self.service_client.handle_webhook(body, headers, method, path)
5863

5964
def handle_directory_webhook(self, body, headers, method, path):
6065
return self.directory_client.handle_webhook(body, headers, method, path)

examples/flask-webhooks-example/launchkey_example_app/views/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from flask.views import MethodView
33

44
from launchkey.entities.directory import DeviceLinkCompletionResponse
5-
from launchkey.entities.service import AuthorizationResponse, SessionEndRequest
5+
from launchkey.entities.service import AuthorizationResponse, AdvancedAuthorizationResponse, SessionEndRequest
66
from launchkey.exceptions import AuthorizationInProgress
77

88

@@ -165,7 +165,8 @@ def __init__(self, launchkey_service, database_service, logger):
165165
def post(self):
166166
package = self.launchkey_service.handle_service_webhook(
167167
request.data, request.headers, request.method, request.path)
168-
if isinstance(package, AuthorizationResponse):
168+
if isinstance(package, AdvancedAuthorizationResponse) or isinstance(package, AuthorizationResponse):
169+
self.logger.info(f"Service Webhook Received {type(package)}")
169170
auth_request = self.database_service.get_auth_request(
170171
package.authorization_request_id)
171172
if auth_request:

features/base_environment.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ def before_all(context):
1515
context.organization_private_key,
1616
url=getattr(context, 'launchkey_url', LAUNCHKEY_PRODUCTION)
1717
)
18-
sample_app_package = 'com.launchkey.android.authenticator.demo'
18+
sample_app_package = 'com.launchkey.android.authenticator.demo.javaApp'
1919

2020
desired_caps = dict()
2121
# Increase the default idle time in order to prevent the session from
2222
# closing while non device tests are being ran.
23-
desired_caps['newCommandTimeout'] = 300
23+
desired_caps['newCommandTimeout'] = 600
2424
desired_caps['appPackage'] = sample_app_package
2525
desired_caps[
2626
'appWaitActivity'] = 'com.launchkey.android.authenticator.demo.' \

features/directory_client/devices/directory-client-device-link.feature

+6-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ Feature: Directory Client can link Devices
1212
And the Device linking response contains a valid Linking Code
1313
And the Device linking response contains a valid Device ID
1414

15+
Scenario: Linking Devices with TTL returns QR Code URL and linking code
16+
When I make a Device linking request with a TTL of 300 seconds
17+
Then the Device linking response contains a valid QR Code URL
18+
And the Device linking response contains a valid Linking Code
19+
1520
Scenario: Linking Devices adds the device to the User's Device list
1621
When I make a Device linking request
1722
And I retrieve the Devices list for the current User
@@ -25,4 +30,4 @@ Feature: Directory Client can link Devices
2530
When I link my device
2631
And I retrieve the Devices list for the current User
2732
Then there should be 1 Device in the Devices list
28-
And all of the devices should be active
33+
And all of the devices should be active

features/directory_client/devices/directory-client-device-unlink.feature

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Feature: Directory Client can unlink devices
1414
Then there should be 0 Devices in the Devices list
1515

1616
Scenario: Unlinking invalid Device throws NotFoundException
17+
Given I have made a Device linking request
1718
When I attempt to unlink the device with the ID "67c87654-aed9-11e7-98e9-0469f8dc10a5"
1819
Then a EntityNotFound error occurs
1920

features/directory_client/services/policy/directory-client-service-policy-get.feature

+139
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,142 @@ Feature: Directory Client can retrieve Directory Service Policy
6363
Scenario: Getting the policy for invalid Service throws Forbidden
6464
When I attempt to retrieve the Policy for the Directory Service with the ID "eba60cb8-c649-11e7-abc4-cec278b6b50a"
6565
Then a ServiceNotFound error occurs
66+
67+
Scenario: Setting Fences on a Method Amount Policy works as expected
68+
When I create a new MethodAmountPolicy
69+
And I add the following GeoCircleFence items
70+
| latitude | longitude | radius | name |
71+
| 45.1250 | 150.51 | 15200 | Large Fence |
72+
| -50.0111 | -140 | 100 | Small Fence |
73+
And I add the following TerritoryFence items
74+
| country | admin_area | postal_code | name |
75+
| US | US-NV | 89120 | US-NV |
76+
| US | US-CA | 90001 | US-CA |
77+
And I set the Advanced Policy for the Current Directory Service to the new policy
78+
And I retrieve the Advanced Policy for the Current Directory Service
79+
Then the Directory Service Policy has "4" fences
80+
And the Directory Service Policy contains the GeoCircleFence "Large Fence"
81+
And the "Large Fence" fence has a latitude of "45.1250"
82+
And the "Large Fence" fence has a longitude of "150.51"
83+
And the "Large Fence" fence has a radius of "15200"
84+
And the Directory Service Policy contains the GeoCircleFence "Small Fence"
85+
And the "Small Fence" fence has a latitude of "-50.0111"
86+
And the "Small Fence" fence has a longitude of "-140"
87+
And the "Small Fence" fence has a radius of "100"
88+
And the Directory Service Policy contains the TerritoryFence "US-NV"
89+
And the "US-NV" fence has a country of "US"
90+
And the "US-NV" fence has an administrative_area of "US-NV"
91+
And the "US-NV" fence has a postal_code of "89120"
92+
And the Directory Service Policy contains the TerritoryFence "US-CA"
93+
And the "US-CA" fence has a country of "US"
94+
And the "US-CA" fence has an administrative_area of "US-CA"
95+
And the "US-CA" fence has a postal_code of "90001"
96+
97+
Scenario: Setting Fences on a Factors Policy works as expected
98+
When I create a new Factors Policy
99+
And I set the factors to "KNOWLEDGE"
100+
And I add the following GeoCircleFence items
101+
| latitude | longitude | radius | name |
102+
| 45.1250 | 150.51 | 15200 | Large Fence |
103+
| -50.0111 | -140 | 100 | Small Fence |
104+
And I add the following TerritoryFence items
105+
| country | admin_area | postal_code | name |
106+
| US | US-NV | 89120 | US-NV |
107+
| US | US-CA | 90001 | US-CA |
108+
And I set the Advanced Policy for the Current Directory Service to the new policy
109+
And I retrieve the Advanced Policy for the Current Directory Service
110+
Then the Directory Service Policy has "4" fences
111+
And the Directory Service Policy contains the GeoCircleFence "Large Fence"
112+
And the "Large Fence" fence has a latitude of "45.1250"
113+
And the "Large Fence" fence has a longitude of "150.51"
114+
And the "Large Fence" fence has a radius of "15200"
115+
And the Directory Service Policy contains the GeoCircleFence "Small Fence"
116+
And the "Small Fence" fence has a latitude of "-50.0111"
117+
And the "Small Fence" fence has a longitude of "-140"
118+
And the "Small Fence" fence has a radius of "100"
119+
And the Directory Service Policy contains the TerritoryFence "US-NV"
120+
And the "US-NV" fence has a country of "US"
121+
And the "US-NV" fence has an administrative_area of "US-NV"
122+
And the "US-NV" fence has a postal_code of "89120"
123+
And the Directory Service Policy contains the TerritoryFence "US-CA"
124+
And the "US-CA" fence has a country of "US"
125+
And the "US-CA" fence has an administrative_area of "US-CA"
126+
And the "US-CA" fence has a postal_code of "90001"
127+
128+
Scenario: Setting Inside Policy to Factors Policy works as expected
129+
Given the Directory Service is set to any Conditional Geofence Policy
130+
When I set the inside Policy to a new Factors Policy
131+
And I set the inside Policy factors to "Knowledge"
132+
And I set the Advanced Policy for the Current Directory Service to the new policy
133+
And I retrieve the Advanced Policy for the Current Directory Service
134+
Then the inside Policy should be a FactorsPolicy
135+
And the inside Policy factors should be set to "Knowledge"
136+
And deny_rooted_jailbroken should be set to "False"
137+
And deny_emulator_simulator should be set to "False"
138+
And the Directory Service Policy has "1" fence
139+
140+
Scenario: Setting Inside Policy to Methods Amount Policy works as expected
141+
Given the Directory Service is set to any Conditional Geofence Policy
142+
When I set the inside Policy to a new MethodAmountPolicy
143+
And I set the inside Policy amount to "2"
144+
And I set the Advanced Policy for the Current Directory Service to the new policy
145+
And I retrieve the Advanced Policy for the Current Directory Service
146+
Then the inside Policy should be a MethodAmountPolicy
147+
And the inside Policy amount should be set to "2"
148+
And deny_rooted_jailbroken should be set to "False"
149+
And deny_emulator_simulator should be set to "False"
150+
And the Directory Service Policy has "1" fence
151+
152+
Scenario: Setting Outside Policy to Factors Policy works as expected
153+
Given the Directory Service is set to any Conditional Geofence Policy
154+
When I set the outside Policy to a new Factors Policy
155+
And I set the outside Policy factors to "Knowledge"
156+
And I set the Advanced Policy for the Current Directory Service to the new policy
157+
And I retrieve the Advanced Policy for the Current Directory Service
158+
Then the outside Policy should be a FactorsPolicy
159+
And the outside Policy factors should be set to "Knowledge"
160+
And deny_rooted_jailbroken should be set to "False"
161+
And deny_emulator_simulator should be set to "False"
162+
And the Directory Service Policy has "1" fence
163+
164+
Scenario: Setting Outside Policy to Methods Amount Policy works as expected
165+
Given the Directory Service is set to any Conditional Geofence Policy
166+
When I set the outside Policy to a new MethodAmountPolicy
167+
And I set the outside Policy amount to "2"
168+
And I set the Advanced Policy for the Current Directory Service to the new policy
169+
And I retrieve the Advanced Policy for the Current Directory Service
170+
Then the outside Policy should be a MethodAmountPolicy
171+
And the outside Policy amount should be set to "2"
172+
And deny_rooted_jailbroken should be set to "False"
173+
And deny_emulator_simulator should be set to "False"
174+
And the Directory Service Policy has "1" fence
175+
176+
Scenario: Setting Fences on a Conditional Geofence Policy works as expected
177+
Given the Directory Service is set to any Conditional Geofence Policy
178+
When I add the following GeoCircleFence items
179+
| latitude | longitude | radius | name |
180+
| 45.1250 | 150.51 | 15200 | Large Fence |
181+
| -50.0111 | -140 | 100 | Small Fence |
182+
And I add the following TerritoryFence items
183+
| country | admin_area | postal_code | name |
184+
| US | US-NV | 89120 | US-NV |
185+
| US | US-CA | 90001 | US-CA |
186+
And I set the Advanced Policy for the Current Directory Service to the new policy
187+
And I retrieve the Advanced Policy for the Current Directory Service
188+
Then the Directory Service Policy has "5" fences
189+
And the Directory Service Policy contains the GeoCircleFence "Large Fence"
190+
And the "Large Fence" fence has a latitude of "45.1250"
191+
And the "Large Fence" fence has a longitude of "150.51"
192+
And the "Large Fence" fence has a radius of "15200"
193+
And the Directory Service Policy contains the GeoCircleFence "Small Fence"
194+
And the "Small Fence" fence has a latitude of "-50.0111"
195+
And the "Small Fence" fence has a longitude of "-140"
196+
And the "Small Fence" fence has a radius of "100"
197+
And the Directory Service Policy contains the TerritoryFence "US-NV"
198+
And the "US-NV" fence has a country of "US"
199+
And the "US-NV" fence has an administrative_area of "US-NV"
200+
And the "US-NV" fence has a postal_code of "89120"
201+
And the Directory Service Policy contains the TerritoryFence "US-CA"
202+
And the "US-CA" fence has a country of "US"
203+
And the "US-CA" fence has an administrative_area of "US-CA"
204+
And the "US-CA" fence has a postal_code of "90001"

0 commit comments

Comments
 (0)