Skip to content

Commit

Permalink
Merge pull request #103 from getyoti/release-2.9.0
Browse files Browse the repository at this point in the history
Release 2.9.0
  • Loading branch information
MrBurtyyy authored Sep 16, 2019
2 parents b6eec66 + 149f6be commit e39c365
Show file tree
Hide file tree
Showing 53 changed files with 2,455 additions and 373 deletions.
4 changes: 3 additions & 1 deletion .coveragerc
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[run]
omit=yoti/tests/*
omit =
yoti_python_sdk/tests/**
examples/**
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ htmlcov/
.cache
nosetests.xml
coverage.*
coverage-reports
*,cover
.hypothesis/

Expand Down Expand Up @@ -103,4 +104,4 @@ examples/yoti_example_flask/static/YotiSelfie.jpg
examples/yoti_example_django/*.pem
examples/yoti_example_flask/*.pem

.scannerwork
.scannerwork
2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MASTER]
ignore=yoti_python_sdk/tests/**,examples/**
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,11 @@ Running the tests is done by the following process, ensuring you are using Pytho
* [X] Address `postal_address`
* [X] Gender `gender`
* [X] Nationality `nationality`
* [X] Application Profile `application_profile`
* [X] Name `application_name`
* [X] URL `application_url`
* [X] Logo `application_logo`
* [X] Receipt Background Color `application_receipt_bg_color`
* [X] Base64 Selfie URI `base64_selfie_uri`

## Support
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<span class="yoti-attribute-name-cell-text">{{ name }}</span>
</div>
</div>

<div class="yoti-attribute-value">
<div class="yoti-attribute-value-text">
{% if prop.name == "document_images" %}
Expand Down Expand Up @@ -34,6 +34,21 @@
</tr>
{% endfor %}
</table>
{% elif prop.name == "age_verified" %}
<table>
<tr>
<td>Check Type</td>
<td>{{ prop.value.check_type }}</td>
</tr>
<tr>
<td>Age</td>
<td>{{ prop.value.age }}</td>
</tr>
<tr>
<td>Result</td>
<td>{{ prop.value.result }}</td>
</tr>
</table>
{% else %}
{{ prevalue }}
{{ prop.value }}
Expand Down
7 changes: 6 additions & 1 deletion examples/yoti_example_django/yoti_example/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@
from django.conf.urls import url
from django.contrib import admin

from .views import IndexView, AuthView, DynamicShareView
from .views import IndexView, AuthView, DynamicShareView, SourceConstraintsView

urlpatterns = [
url(r"^$", IndexView.as_view(), name="index"),
url(r"^yoti/auth/$", AuthView.as_view(), name="auth"),
url(r"^admin/", admin.site.urls),
url(r"^dynamic-share/$", DynamicShareView.as_view(), name="dynamic-share"),
url(
r"^source-constraint/$",
SourceConstraintsView.as_view(),
name="source-constraints",
),
]
47 changes: 43 additions & 4 deletions examples/yoti_example_django/yoti_example/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
DynamicScenarioBuilder,
create_share_url,
)
from yoti_python_sdk.dynamic_sharing_service.policy import DynamicPolicyBuilder
from yoti_python_sdk.dynamic_sharing_service.policy import (
DynamicPolicyBuilder,
SourceConstraintBuilder,
)

load_dotenv(find_dotenv())

Expand Down Expand Up @@ -53,6 +56,34 @@ def get(self, request, *args, **kwargs):
return self.render_to_response(context)


class SourceConstraintsView(TemplateView):
template_name = "dynamic-share.html"

def get(self, request, *args, **kwargs):
client = Client(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)
constraint = (
SourceConstraintBuilder().with_driving_licence().with_passport().build()
)
policy = (
DynamicPolicyBuilder()
.with_full_name(constraints=constraint)
.with_structured_postal_address(constraints=constraint)
.build()
)
scenario = (
DynamicScenarioBuilder()
.with_policy(policy)
.with_callback_endpoint("/yoti/auth")
.build()
)
share = create_share_url(client, scenario)
context = {
"yoti_client_sdk_id": YOTI_CLIENT_SDK_ID,
"yoti_share_url": share.share_url,
}
return self.render_to_response(context)


class AuthView(TemplateView):
template_name = "profile.html"

Expand All @@ -71,10 +102,18 @@ def get(self, request, *args, **kwargs):
context["receipt_id"] = getattr(activity_details, "receipt_id")
context["timestamp"] = getattr(activity_details, "timestamp")

# change this string according to the age condition defined in Yoti Hub
age_verified = profile.get_attribute("age_over:18")
# change this number according to the age condition defined in Yoti Hub
age_verified = profile.find_age_over_verification(18)

# Age verification objects don't have the same properties as an attribute,
# so for this example we had to mock an object with the same properties
if age_verified is not None:
context["age_verified"] = age_verified
context["age_verified"] = {
"name": "age_verified",
"value": age_verified,
"sources": age_verified.attribute.sources,
"verifiers": age_verified.attribute.verifiers,
}

selfie = context.get("selfie")
if selfie is not None:
Expand Down
45 changes: 41 additions & 4 deletions examples/yoti_example_flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
from flask import Flask, render_template, request

from yoti_python_sdk import Client
from yoti_python_sdk.dynamic_sharing_service.policy import DynamicPolicyBuilder
from yoti_python_sdk.dynamic_sharing_service.policy import (
DynamicPolicyBuilder,
SourceConstraintBuilder,
)
from yoti_python_sdk.dynamic_sharing_service import DynamicScenarioBuilder
from yoti_python_sdk.dynamic_sharing_service import create_share_url

Expand Down Expand Up @@ -52,6 +55,32 @@ def dynamic_share():
)


@app.route("/source-constraints")
def source_constraints():
client = Client(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)
constraint = (
SourceConstraintBuilder().with_driving_licence().with_passport().build()
)
policy = (
DynamicPolicyBuilder()
.with_full_name(constraints=constraint)
.with_structured_postal_address(constraints=constraint)
.build()
)
scenario = (
DynamicScenarioBuilder()
.with_policy(policy)
.with_callback_endpoint("/yoti/auth")
.build()
)
share = create_share_url(client, scenario)
return render_template(
"dynamic-share.html",
yoti_client_sdk_id=YOTI_CLIENT_SDK_ID,
yoti_share_url=share.share_url,
)


@app.route("/yoti/auth")
def auth():
client = Client(YOTI_CLIENT_SDK_ID, YOTI_KEY_FILE_PATH)
Expand All @@ -68,10 +97,18 @@ def auth():
context["receipt_id"] = getattr(activity_details, "receipt_id")
context["timestamp"] = getattr(activity_details, "timestamp")

# change this string according to the age condition defined in Yoti Hub
age_verified = profile.get_attribute("age_over:18")
# change this number according to the age condition defined in Yoti Hub
age_verified = profile.find_age_over_verification(18)

# Age verification objects don't have the same properties as an attribute,
# so for this example we had to mock an object with the same properties
if age_verified is not None:
context["age_verified"] = age_verified
context["age_verified"] = {
"name": "age_verified",
"value": age_verified,
"sources": age_verified.attribute.sources,
"verifiers": age_verified.attribute.verifiers,
}

selfie = context.get("selfie")
if selfie is not None:
Expand Down
19 changes: 19 additions & 0 deletions examples/yoti_example_flask/templates/profile.html
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,23 @@
</table>
{% endmacro %}

{% macro parse_age_verification(prop) %}
<table>
<tr>
<td>Check Type</td>
<td>{{ prop.value.check_type }}</td>
</tr>
<tr>
<td>Age</td>
<td>{{ prop.value.age }}</td>
</tr>
<tr>
<td>Result</td>
<td>{{ prop.value.result }}</td>
</tr>
</table>
{% endmacro %}

{% macro attribute(name, icon, prop, prevalue="") %}
{% if prop %}
{% if prop.value %}
Expand All @@ -48,6 +65,8 @@
{{ parse_structured_address(prop) }}
{% elif prop.name == "document_details" %}
{{ parse_document_details(prop) }}
{% elif prop.name == "age_verified" %}
{{ parse_age_verification(prop) }}
{% else %}
{{ prevalue }}
{{ prop.value }}
Expand Down
4 changes: 2 additions & 2 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[pytest]
testpaths = yoti_python_sdk/tests
norecursedirs = venv
testpaths = yoti_python_sdk/tests/
norecursedirs = venv
7 changes: 7 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
sonar.projectKey = yoti-web-sdk:python
sonar.projectName = python-sdk
sonar.projectVersion = 2.9.0
sonar.exclusions=yoti_python_sdk/tests/**,examples/**

sonar.python.pylint.reportPath=coverage.out
sonar.verbose = true
17 changes: 13 additions & 4 deletions yoti_python_sdk/activity_details.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@


class ActivityDetails:
def __init__(self, receipt, decrypted_profile=None, decrypted_application_profile=None):
def __init__(
self, receipt, decrypted_profile=None, decrypted_application_profile=None
):
self.decrypted_profile = decrypted_profile
self.user_profile = {} # will be removed in v3.0.0
self.base64_selfie_uri = None
Expand Down Expand Up @@ -57,9 +59,15 @@ def __init__(self, receipt, decrypted_profile=None, decrypted_application_profil

self.ensure_postal_address()

if decrypted_application_profile and hasattr(decrypted_application_profile, "attributes"):
decrypted_application_profile_attributes = decrypted_application_profile.attributes
self.application_profile = ApplicationProfile(decrypted_application_profile_attributes)
if decrypted_application_profile and hasattr(
decrypted_application_profile, "attributes"
):
decrypted_application_profile_attributes = (
decrypted_application_profile.attributes
)
self.application_profile = ApplicationProfile(
decrypted_application_profile_attributes
)

self.__remember_me_id = receipt.get("remember_me_id")
self.parent_remember_me_id = receipt.get("parent_remember_me_id")
Expand All @@ -84,6 +92,7 @@ def user_id(self):
def user_id(self, value):
self.__remember_me_id = value

@deprecated
def try_parse_age_verified_field(self, field):
if field is not None:
age_verified = attribute_parser.value_based_on_content_type(
Expand Down
44 changes: 44 additions & 0 deletions yoti_python_sdk/age_verification.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from yoti_python_sdk.exceptions import MalformedAgeVerificationException
from yoti_python_sdk import config


class AgeVerification(object):
def __init__(self, derived_attribute):
self.__derived_attribute = derived_attribute

split = derived_attribute.name.split(":")
if len(split) != 2:
raise MalformedAgeVerificationException

if (
split[0] in config.ATTRIBUTE_AGE_OVER
or split[0] in config.ATTRIBUTE_AGE_UNDER
):
self.__check_type = split[0]
else:
raise MalformedAgeVerificationException

try:
self.__age_verified = int(split[1])
if derived_attribute.value == "true":
self.__result = True
elif derived_attribute.value == "false":
self.__result = False
except Exception:
raise MalformedAgeVerificationException

@property
def age(self):
return self.__age_verified

@property
def check_type(self):
return self.__check_type

@property
def result(self):
return self.__result

@property
def attribute(self):
return self.__derived_attribute
15 changes: 12 additions & 3 deletions yoti_python_sdk/anchor.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,21 @@
class Anchor:
def __init__(
self,
anchor_type=UNKNOWN_ANCHOR_TYPE,
sub_type="",
value="",
anchor_type=None,
sub_type=None,
value=None,
signed_timestamp=None,
origin_server_certs=None,
):
if sub_type is None:
sub_type = ""

if value is None:
value = ""

if anchor_type is None:
anchor_type = UNKNOWN_ANCHOR_TYPE

self.__anchor_type = anchor_type
self.__sub_type = sub_type
self.__value = value
Expand Down
6 changes: 5 additions & 1 deletion yoti_python_sdk/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@


class Attribute:
def __init__(self, name="", value="", anchors=None):
def __init__(self, name=None, value=None, anchors=None):
if name is None:
name = ""
if value is None:
value = ""
if anchors is None:
anchors = {}
self.__name = name
Expand Down
Loading

0 comments on commit e39c365

Please sign in to comment.