Skip to content

Commit 68de001

Browse files
authored
Merge pull request #23 from getyoti/SDK-282-IsAgeVerifiedHelper
[SDK-282]: Added IsAgeVerified helper
2 parents f3a256d + 96fd3e9 commit 68de001

File tree

11 files changed

+128
-31
lines changed

11 files changed

+128
-31
lines changed

README.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ Here is an example of how this works:
117117

118118
```python
119119
client = Client(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)
120-
user_profile = client.get_activity_details(token).user_profile
120+
activity_details = client.get_activity_details(token)
121+
user_profile = activity_details.user_profile
121122

122123
user_id = user_profile.get('user_id')
123124
selfie = user_profile.get('selfie')
@@ -126,9 +127,12 @@ family_name = user_profile.get('family_name')
126127
full_name = user_profile.get('full_name')
127128
phone_number = user_profile.get('phone_number')
128129
date_of_birth = user_profile.get('date_of_birth')
130+
is_age_verified = user_profile.get('is_age_verified')
129131
postal_address = user_profile.get('postal_address')
130132
gender = user_profile.get('gender')
131133
nationality = user_profile.get('nationality')
134+
135+
base64_selfie_uri = activity_details.get('base64_selfie_uri')
132136
```
133137

134138
## AML Integration
@@ -238,30 +242,31 @@ Plugins for both Django and Flask are in the `plugins/` dir. Their purpose is to
238242

239243
## Running the Tests
240244

241-
Run your project but please make sure you have all the correct requirements:
245+
Running the tests is done by the following process, ensuring you are using Python 3.0+:
242246

243247
1. Install dependencies: `pip install -r requirements.txt`
244-
2. Install the SDK: `python setup.py develop`
245-
3. Execute in the main project dir: `py.test`
248+
1. Install the SDK: `python setup.py develop`
249+
1. Execute in the main project dir: `py.test`
246250

247251
For information on testing with multiple Python versions, see [VERSION-SUPPORT.md](/VERSION-SUPPORT.md)
248252

249253
## API Coverage
250254

251255
* Activity Details
252256
* [X] User ID `user_id`
253-
* [X] Profile
257+
* [X] Profile `user_profile`
254258
* [X] Photo `selfie`
255259
* [X] Given Names `given_names`
256260
* [X] Family Name `family_name`
257261
* [X] Full Name `full_name`
258262
* [X] Mobile Number `phone_number`
259263
* [X] Email Address `email_address`
260264
* [X] Age / Date of Birth `date_of_birth`
261-
* [X] Age / Verify Condition `age_[over|under]:[1-999]`
265+
* [X] Age / Is Age Verified `is_age_verified`
262266
* [X] Address `postal_address`
263267
* [X] Gender `gender`
264268
* [X] Nationality `nationality`
269+
* [X] Base64 Selfie URI `base64_selfie_uri`
265270

266271
## Support
267272

examples/yoti_example_django/yoti_example/templates/profile.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ <h3><a href="/">Home</a></h3>
6060
</tr>
6161
{% endif %}
6262

63-
{% if age_verified %}
63+
{% if is_age_verified is not None %}
6464
<tr>
6565
<td>Age Verified:</td>
66-
<td>{{age_verified}}</td>
66+
<td>{{is_age_verified}}</td>
6767
</tr>
6868
{% endif %}
6969

examples/yoti_example_django/yoti_example/views.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@ def get(self, request, *args, **kwargs):
2626
context = activity_details.user_profile
2727
context['base64_selfie_uri'] = getattr(activity_details, 'base64_selfie_uri')
2828

29-
# This key uses the format: age_[over|under]:[1-999] and is dynamically
30-
# generated based on the dashboard attribute Age / Verify Condition
31-
context['age_verified'] = context.get('age_over:18')
3229
selfie = context.get('selfie')
3330
if selfie is not None:
3431
self.save_image(selfie)

examples/yoti_example_flask/app.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,6 @@ def auth():
3838
user_profile = activity_details.user_profile
3939
user_profile['base64_selfie_uri'] = getattr(activity_details, 'base64_selfie_uri')
4040

41-
# This key uses the format: age_[over|under]:[1-999] and is dynamically
42-
# generated based on the dashboard attribute Age / Verify Condition
43-
user_profile['age_verified'] = user_profile.get('age_over:18')
4441
selfie = user_profile.get('selfie')
4542
if selfie is not None:
4643
save_image(selfie)
@@ -49,4 +46,4 @@ def auth():
4946

5047

5148
if __name__ == '__main__':
52-
app.run(host="0.0.0.0", debug=True)
49+
app.run(host="0.0.0.0")

examples/yoti_example_flask/templates/profile.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ <h3><a href="/">Home</a></h3>
6060
</tr>
6161
{% endif %}
6262

63-
{% if age_verified %}
63+
{% if is_age_verified is defined %}
6464
<tr>
6565
<td>Age Verified:</td>
66-
<td>{{age_verified}}</td>
66+
<td>{{is_age_verified}}</td>
6767
</tr>
6868
{% endif %}
6969

plugins/django_yoti/django_yoti/tests/test_views.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.test import TestCase, Client, RequestFactory
44

55
from yoti_python_sdk.activity_details import ActivityDetails
6+
from yoti_python_sdk.tests.conftest import successful_receipt, failure_receipt
67
from ..views import profile
78

89

@@ -31,10 +32,7 @@ def test_profile_not_logged_in(self):
3132
self.assertEqual(response.url, '/login/')
3233

3334
def test_profile_outcome_is_failure(self):
34-
receipt = {'remember_me_id': 'some_id',
35-
'sharing_outcome': 'FAILURE'}
36-
activity_details = ActivityDetails(receipt, None)
37-
35+
activity_details = ActivityDetails(failure_receipt(), None)
3836
request = self.factory.get('/profile/')
3937
self._update_session(request, activity_details=dict(activity_details))
4038
response = profile(request)

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
from setuptools import setup, find_packages
33

4-
VERSION = '2.1.0'
4+
VERSION = '2.2.0'
55
long_description = 'This package contains the tools you need to quickly ' \
66
'integrate your Python back-end with Yoti, so that your ' \
77
'users can share their identity details with your ' \

yoti_python_sdk/activity_details.py

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# -*- coding: utf-8 -*-
2+
from yoti_python_sdk import config
23
from yoti_python_sdk.protobuf.v1.protobuf import Protobuf
34

45

56
class ActivityDetails:
67
def __init__(self, receipt, decrypted_profile=None):
78
self.decrypted_profile = decrypted_profile
89
self.user_profile = {}
9-
self.base64_selfie_uri = ''
10+
self.base64_selfie_uri = None
1011

1112
if decrypted_profile and hasattr(decrypted_profile, 'attributes'):
1213
for field in decrypted_profile.attributes:
@@ -15,15 +16,35 @@ def __init__(self, receipt, decrypted_profile=None):
1516
field.content_type
1617
)
1718
self.user_profile[field.name] = value
18-
if field.name == 'selfie':
19-
self.base64_selfie_uri = Protobuf().image_uri_based_on_content_type(
20-
field.value,
21-
field.content_type
22-
)
19+
20+
self.try_parse_selfie_field(field)
21+
self.try_parse_age_verified_field(field)
2322

2423
self.user_id = receipt['remember_me_id']
2524
self.outcome = receipt['sharing_outcome']
2625

26+
def try_parse_selfie_field(self, field):
27+
if field.name == 'selfie':
28+
self.base64_selfie_uri = Protobuf().image_uri_based_on_content_type(
29+
field.value,
30+
field.content_type
31+
)
32+
33+
def try_parse_age_verified_field(self, field):
34+
if field.name.startswith(config.ATTRIBUTE_AGE_OVER) or field.name.startswith(config.ATTRIBUTE_AGE_UNDER):
35+
is_age_verified = Protobuf().value_based_on_content_type(
36+
field.value,
37+
field.content_type
38+
)
39+
if is_age_verified == 'true':
40+
self.user_profile['is_age_verified'] = True
41+
return
42+
if is_age_verified == 'false':
43+
self.user_profile['is_age_verified'] = False
44+
return
45+
else:
46+
raise TypeError("age_verified_field unable to be parsed")
47+
2748
def __iter__(self):
2849
yield 'user_id', self.user_id
2950
yield 'outcome', self.outcome

yoti_python_sdk/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
# -*- coding: utf-8 -*-
22
SDK_IDENTIFIER = "Python"
3+
ATTRIBUTE_AGE_OVER = "age_over:"
4+
ATTRIBUTE_AGE_UNDER = "age_under:"

yoti_python_sdk/tests/conftest.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
2-
from os.path import dirname, join, abspath
3-
42
import pytest
3+
import io
4+
from os.path import dirname, join, abspath
55

66
from yoti_python_sdk import Client
77
from yoti_python_sdk.crypto import Crypto
@@ -39,6 +39,23 @@ def decrypted_request_token():
3939
'470c-48e5-8ceb-25cf86674ba4'
4040

4141

42+
@pytest.fixture(scope='module')
43+
def user_id():
44+
return 'some_id'
45+
46+
47+
@pytest.fixture(scope='module')
48+
def successful_receipt():
49+
return {'remember_me_id': user_id(),
50+
'sharing_outcome': 'SUCCESS'}
51+
52+
53+
@pytest.fixture(scope='module')
54+
def failure_receipt():
55+
return {'remember_me_id': user_id(),
56+
'sharing_outcome': 'FAILURE'}
57+
58+
4259
@pytest.fixture(scope='module')
4360
def x_yoti_auth_key():
4461
with open(AUTH_KEY_FILE_PATH, 'r') as auth_key_file:
@@ -53,5 +70,5 @@ def x_yoti_auth_digest_get():
5370

5471
@pytest.fixture(scope='module')
5572
def x_yoti_auth_digest_post():
56-
with open(AUTH_DIGEST_POST_FILE_PATH, 'r') as auth_digest_file:
73+
with io.open(AUTH_DIGEST_POST_FILE_PATH, mode='r', encoding='utf-8') as auth_digest_file:
5774
return auth_digest_file.read()

0 commit comments

Comments
 (0)