Skip to content

Commit 3508afc

Browse files
AnatoliiSrszalski
authored andcommitted
Feature/django plugin (#15)
* DjangoYoti plugin init commit * Adds unittests
1 parent 62b4859 commit 3508afc

30 files changed

+955
-0
lines changed

plugins/django_yoti/LICENSE

Whitespace-only changes.

plugins/django_yoti/MANIFEST.in

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include LICENSE
2+
include README.md
3+
recursive-include django_yoti/templates *.html
4+
recursive-include example/yoti_example/templates *.html

plugins/django_yoti/README.md

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
# Django Yoti #
2+
3+
Description
4+
5+
## Plugin configuration ##
6+
### General settings ###
7+
8+
* First you need to add `django_yoti` plugin to your INSTALLED_APPS setting like this:
9+
```python
10+
# your_django_project/settings.py
11+
12+
...
13+
14+
INSTALLED_APPS = [
15+
...
16+
'django_yoti',
17+
]
18+
```
19+
20+
* In order to use context tags inside your template (`{{ yoti_site_verification }}`, `{{ yoti_login_button_*}}`),
21+
you should include `django_yoti`'s context processors into your templates configuration like this:
22+
```python
23+
# your_django_project/settings.py
24+
25+
...
26+
27+
TEMPLATES = [
28+
{
29+
...
30+
'OPTIONS': {
31+
'context_processors': [
32+
...
33+
'django_yoti.context_processors.yoti_context',
34+
],
35+
},
36+
},
37+
]
38+
```
39+
40+
* And then use the following settings to configure the plugin:
41+
42+
43+
```python
44+
# your_django_project/settings.py
45+
46+
...
47+
48+
YOTI = {
49+
'YOTI_APPLICATION_ID': '...',
50+
'YOTI_CLIENT_SDK_ID': '...',
51+
'YOTI_KEY_FILE_PATH': '...',
52+
'YOTI_VERIFICATION_KEY': '...',
53+
...
54+
}
55+
```
56+
* **`YOTI_APPLICATION_ID`** - **required**, *can be also set by env variable with the same name*<br>
57+
Your Yoti application's ID, found under the `INTEGRATIONS` tab of your
58+
Yoti application's settings page ([Yoti Dashboard](https://www.yoti.com/dashboard/)).<br>
59+
It is used to configure the [Yoti Login Button](https://www.yoti.com/developers/#login-button-setup).<br>
60+
Example: `ca84f68b-1b48-458b-96bf-963868edc8b6`
61+
62+
* **`YOTI_CLIENT_SDK_ID`** - **required**, *can be also set by env variable with the same name*<br>
63+
Your Yoti application's SDK ID, found under the `INTEGRATIONS` tab of your
64+
Yoti application's settings page ([Yoti Dashboard](https://www.yoti.com/dashboard/)).<br>
65+
Example: `39aef70a-89d6-4644-a687-b3e891613da6`
66+
67+
* **`YOTI_KEY_FILE_PATH`** - **required**, *can be also set by env variable with the same name*<br>
68+
The full path to your private key downloaded from your Yoti application's
69+
settings page under the `KEYS` tab ([Yoti Dashboard](https://www.yoti.com/dashboard/)).<br>
70+
Example: `/home/user/.ssh/access-security.pem`
71+
72+
* **`YOTI_VERIFICATION_KEY`** - *can be also set by env variable with the same name*<br>
73+
A key, used to verify your callback URL. Can be found under the
74+
`INTEGRATIONS` tab of your Yoti application's settings page (Callback URL -> VERIFY).<br>
75+
Example: `b14886f972d0c717`
76+
77+
78+
### Endpoints configuration ###
79+
80+
`django_yoti` plugin provides some default endpoints:
81+
```python
82+
# django_yoti/urls.py
83+
84+
urlpatterns = [
85+
url(r'^auth/', views.auth, name='yoti_auth'),
86+
url(r'^login/', views.login, name='yoti_login'),
87+
url(r'^profile/', views.profile, name='yoti_profile')
88+
]
89+
```
90+
`yoti_auth` url is used for receiving token via callback and should'nt be changed.<br>
91+
The last two URLs are examples and can be overridden by the following settings:
92+
93+
```python
94+
# your_django_project/settings.py
95+
96+
...
97+
98+
YOTI = {
99+
...
100+
'YOTI_LOGIN_VIEW': '...',
101+
'YOTI_REDIRECT_TO': '...',
102+
'YOTI_LOGIN_BUTTON_LABEL': '...',
103+
}
104+
```
105+
* **`YOTI_LOGIN_VIEW`**<br>
106+
If *not* authenticated user is trying to access a view with
107+
`@yoti_authenticated` decorator, he/she will be redirected to this view.
108+
Example: `login`<br>
109+
In case you have something like this in your project's `urls.py` file:
110+
```python
111+
urlpatterns = [
112+
...
113+
url(r'^login/', views.login, name='login'),
114+
...
115+
]
116+
```
117+
Default value: `yoti_login` (with `/yoti/login/` URL)
118+
119+
* **`YOTI_REDIRECT_TO`**<br>
120+
View name to which user is redirected after successful authentication.<br>
121+
Example: `profile`<br>
122+
In case you have something like this in your project's `urls.py` file:
123+
```python
124+
urlpatterns = [
125+
...
126+
url(r'^profile/', views.profile, name='profile'),
127+
...
128+
]
129+
```
130+
Default value: `yoti_profile` (with `/yoti/profile/` URL
131+
132+
<br>
133+
134+
In order to use `django_yoti` plugin in your project, you should include
135+
the plugin's endpoints in your project's `urls.py` file:
136+
```python
137+
# your_django_project/urls.py
138+
139+
...
140+
141+
urlpatterns = [
142+
...
143+
url(r'^yoti/', include('django_yoti.urls')),
144+
...
145+
]
146+
```
147+
148+
### Yoti application configuration ###
149+
150+
Your Yoti application's callback URL should point to `your_site.com/yoti/auth`.<br>
151+
If you want to add a verification tag into any page (other than `/yoti/auth/`),
152+
you can use a `{{ yoti_site_verification }}` tag inside 'head' tag of that page.
153+
154+
## Using plugin ##
155+
156+
1. First you need to add a login button to some of your view's templates.
157+
- You can do it by using one of the predefined login buttons:
158+
```
159+
{{ yoti_login_button_sm }}
160+
{{ yoti_login_button_md }}
161+
{{ yoti_login_button_lg }}
162+
```
163+
- or with a default one `{{ yoti_login_button }}`, in case you're using DTL
164+
as a template language)
165+
- or with `{{ yoti_login_button(size='small', text='Log In with Yoti')`, in
166+
case you're using Jinja2 as your template language<br>
167+
Available button sizes: `small`, `medium`, `large`
168+
169+
By clicking this button, user will be redirected to the Yoti Authentication page.
170+
171+
*Remember to add an appropriate script to your page with login
172+
button in order for it to work. See: [Yoti Developers Documentation](https://www.yoti.com/developers/#login-button-setup)*
173+
174+
2. After successful authentication, user will be redirected to a view,
175+
provided by the `YOTI_REDIRECT_TO` setting.
176+
3. In order to have an access to an authenticated user's information inside a view,
177+
you should use a `@yoti_authenticated` decorator.
178+
Example:
179+
```python
180+
from django_yoti import yoti_authenticated
181+
182+
@yoti_authenticated
183+
def profile_view(request):
184+
user_id = request.yoti_user_id
185+
user_profile = request.yoti_user_profile
186+
return render(request, 'profile.html', user_profile)
187+
```
188+
189+
4. All *not authenticated* users trying to access endpoint with this decorator,
190+
will be redirected to an endpoint, provided by the `YOTI_LOGIN_VIEW` setting.
191+
192+
## Tests ##
193+
194+
To run unit tests just type: `python django_yoti/runtests.py`
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .decorators import yoti_authenticated
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class DjangoYotiConfig(AppConfig):
5+
name = 'django_yoti'
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from django.utils.html import format_html
2+
3+
from .login_button import get_login_button_html
4+
from .settings import YOTI_VERIFICATION_KEY, YOTI_APPLICATION_ID
5+
6+
7+
def yoti_context(request):
8+
context = login_button_context(request)
9+
context.update(site_verification_context(request))
10+
context.update(application_context(request))
11+
return context
12+
13+
14+
def login_button_context(request):
15+
return {
16+
'yoti_login_button': get_login_button_html,
17+
'yoti_login_button_sm': get_login_button_html('small'),
18+
'yoti_login_button_md': get_login_button_html('medium'),
19+
'yoti_login_button_lg': get_login_button_html('large')
20+
}
21+
22+
23+
def site_verification_context(request):
24+
raw_text = '<meta name="yoti-site-verification" content="{0}">'.format(
25+
YOTI_VERIFICATION_KEY
26+
)
27+
return {'yoti_site_verification': format_html(raw_text)}
28+
29+
30+
def application_context(request):
31+
return {'yoti_application_id': YOTI_APPLICATION_ID}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from functools import wraps
2+
from django.shortcuts import redirect
3+
from .settings import YOTI_LOGIN_VIEW
4+
5+
6+
def yoti_authenticated(view_func):
7+
@wraps(view_func)
8+
def _decorated(request, *args, **kwargs):
9+
activity_details = request.session.get('activity_details')
10+
if not activity_details or activity_details.get('outcome') != 'SUCCESS':
11+
return redirect(YOTI_LOGIN_VIEW)
12+
13+
yoti_user_id = activity_details.get('user_id')
14+
yoti_user_profile = activity_details.get('user_profile')
15+
setattr(request, 'yoti_user_id', yoti_user_id)
16+
setattr(request, 'yoti_user_profile', yoti_user_profile)
17+
18+
return view_func(request, *args, **kwargs)
19+
20+
return _decorated
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from django.utils.html import format_html
2+
from .settings import YOTI_APPLICATION_ID, YOTI_LOGIN_BUTTON_LABEL
3+
4+
LOGIN_BUTTON_SIZES = ('small', 'medium', 'large')
5+
6+
7+
def get_login_button_html(size=None, text=YOTI_LOGIN_BUTTON_LABEL):
8+
if size and size not in LOGIN_BUTTON_SIZES:
9+
size = None
10+
data_size = 'data-size="{0}"'.format(size) if size else ''
11+
raw_text = '<span data-yoti-application-id="{0}" {1}>' \
12+
'{2}</span>'.format(YOTI_APPLICATION_ID, data_size, text)
13+
return format_html(raw_text)

plugins/django_yoti/django_yoti/migrations/__init__.py

Whitespace-only changes.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import os
2+
import sys
3+
import django
4+
5+
from django.conf import settings
6+
from django.test.utils import get_runner
7+
8+
9+
# https://docs.djangoproject.com/el/1.10/topics/testing/advanced/
10+
if __name__ == '__main__':
11+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
12+
settings.configure(
13+
DEBUG=True,
14+
DATABASES={
15+
'default': {
16+
'ENGINE': 'django.db.backends.sqlite3',
17+
}
18+
},
19+
ROOT_URLCONF='django_yoti.urls',
20+
INSTALLED_APPS=('django_yoti',
21+
'django.contrib.admin',
22+
'django.contrib.auth',
23+
'django.contrib.contenttypes',
24+
'django.contrib.sessions',
25+
'django.contrib.messages',
26+
'django.contrib.staticfiles'),
27+
TEMPLATES=[
28+
{
29+
'BACKEND': 'django.template.backends.django.DjangoTemplates',
30+
'APP_DIRS': True,
31+
'OPTIONS': {
32+
'context_processors': [
33+
'django_yoti.context_processors.yoti_context',
34+
],
35+
},
36+
},
37+
],
38+
YOTI={
39+
'YOTI_APPLICATION_ID': '01234567-8901-2345-6789-012345678901',
40+
'YOTI_CLIENT_SDK_ID': '01234567-8901-2345-6789-012345678901',
41+
'YOTI_VERIFICATION_KEY': '0123456789012345',
42+
'YOTI_KEY_FILE_PATH': '/home/user/.ssh/yoti_key.pem'
43+
}
44+
)
45+
46+
django.setup()
47+
TestRunner = get_runner(settings)
48+
test_runner = TestRunner()
49+
50+
failures = test_runner.run_tests(['django_yoti'])
51+
sys.exit(bool(failures))

0 commit comments

Comments
 (0)