0001-ovh-ease-setup-with-new-API-47851.patch
passerelle/apps/ovh/migrations/0012_auto_20201019_1556.py | ||
---|---|---|
1 |
# -*- coding: utf-8 -*- |
|
2 |
# Generated by Django 1.11.18 on 2020-10-19 13:56 |
|
3 |
from __future__ import unicode_literals |
|
4 | ||
5 |
from django.db import migrations, models |
|
6 | ||
7 | ||
8 |
class Migration(migrations.Migration): |
|
9 | ||
10 |
dependencies = [ |
|
11 |
('ovh', '0011_auto_20201008_1731'), |
|
12 |
] |
|
13 | ||
14 |
operations = [ |
|
15 |
migrations.AlterField( |
|
16 |
model_name='ovhsmsgateway', |
|
17 |
name='application_key', |
|
18 |
field=models.CharField(blank=True, max_length=16, verbose_name='Application key'), |
|
19 |
), |
|
20 |
migrations.AlterField( |
|
21 |
model_name='ovhsmsgateway', |
|
22 |
name='consumer_key', |
|
23 |
field=models.CharField(blank=True, help_text='Automatically obtained from OVH, should not be filled manually.', max_length=32, verbose_name='Consumer key'), |
|
24 |
), |
|
25 |
] |
passerelle/apps/ovh/models.py | ||
---|---|---|
44 | 44 |
verbose_name=_('Application key'), |
45 | 45 |
max_length=16, |
46 | 46 |
blank=True, |
47 |
help_text=_('Random token obtained from OVH.'), |
|
48 | 47 |
) |
49 | 48 |
application_secret = models.CharField( |
50 | 49 |
verbose_name=_('Application secret'), |
... | ... | |
56 | 55 |
verbose_name=_('Consumer key'), |
57 | 56 |
max_length=32, |
58 | 57 |
blank=True, |
59 |
help_text=_('Obtained at the same time as "Application key".'),
|
|
58 |
help_text=_('Automatically obtained from OVH, should not be filled manually.'),
|
|
60 | 59 |
) |
61 | 60 | |
62 | 61 |
username = models.CharField( |
... | ... | |
131 | 130 | |
132 | 131 |
@property |
133 | 132 |
def uses_new_api(self): |
134 |
return self.application_key and self.consumer_key and self.application_secret
|
|
133 |
return self.application_key and self.application_secret |
|
135 | 134 | |
136 | 135 |
def request(self, method, endpoint, **kwargs): |
137 | 136 |
url = self.API_URL % {'serviceName': self.account, 'login': self.username} |
passerelle/apps/ovh/templates/ovh/ovhsmsgateway_detail.html | ||
---|---|---|
2 | 2 |
{% load i18n passerelle %} |
3 | 3 | |
4 | 4 |
{% block description %} |
5 |
{% if object.uses_new_api and not object.consumer_key %} |
|
6 |
<div class="warningnotice">{% trans "Connector is not operational yet, as access needs to be obtained from OVH for the specified account." %} |
|
7 |
<a href="{% url "ovh-request-token" slug=object.slug %}">{% trans "Click here to request access." %}</a> |
|
8 |
</div> |
|
9 |
{% endif %} |
|
10 | ||
5 | 11 |
{{ block.super }} |
12 | ||
6 | 13 |
{% if object.uses_new_api %} |
7 | 14 |
<p> |
8 | 15 |
{% if object.credit_left %} |
passerelle/apps/ovh/urls.py | ||
---|---|---|
1 |
from django.conf.urls import url |
|
2 | ||
3 |
from . import views |
|
4 | ||
5 |
management_urlpatterns = [ |
|
6 |
url(r'^(?P<slug>[\w,-]+)/request_token/$', |
|
7 |
views.RequestTokenView.as_view(), name='ovh-request-token'), |
|
8 |
url(r'^(?P<slug>[\w,-]+)/confirm_token/(?P<uuid>[a-z0-9-]+)/$', |
|
9 |
views.ConfirmTokenView.as_view(), name='ovh-confirm-token'), |
|
10 |
] |
passerelle/apps/ovh/views.py | ||
---|---|---|
1 |
import requests |
|
2 |
import uuid |
|
3 |
from urllib.parse import urljoin |
|
4 | ||
5 |
from django.conf import settings |
|
6 |
from django.contrib import messages |
|
7 |
from django.shortcuts import reverse |
|
8 |
from django.utils.translation import ugettext_lazy as _ |
|
9 |
from django.views.generic.base import RedirectView |
|
10 | ||
11 |
from .models import OVHSMSGateway |
|
12 | ||
13 | ||
14 |
class RequestTokenView(RedirectView): |
|
15 |
def get_redirect_url(self, *args, **kwargs): |
|
16 |
connector = OVHSMSGateway.objects.get(slug=kwargs["slug"]) |
|
17 | ||
18 |
request_id = uuid.uuid4() |
|
19 |
confirm_token_url = reverse('ovh-confirm-token', kwargs={'slug': connector.slug, 'uuid': request_id}) |
|
20 |
data = { |
|
21 |
"accessRules": [ |
|
22 |
{"method": "GET", "path": "/sms/%s/" % connector.account}, |
|
23 |
{"method": "POST", "path": "/sms/%s/jobs/" % connector.account}, |
|
24 |
], |
|
25 |
"redirection": urljoin(settings.SITE_BASE_URL, confirm_token_url), |
|
26 |
} |
|
27 |
headers = {"X-Ovh-Application": connector.application_key} |
|
28 | ||
29 |
resp = requests.post('https://eu.api.ovh.com/1.0/auth/credential', json=data, headers=headers) |
|
30 |
result = resp.json() |
|
31 | ||
32 |
self.request.session['ovh-token-%s' % request_id] = result['consumerKey'] |
|
33 |
return result['validationUrl'] |
|
34 | ||
35 | ||
36 |
class ConfirmTokenView(RedirectView): |
|
37 |
def get_redirect_url(self, *args, **kwargs): |
|
38 |
connector = OVHSMSGateway.objects.get(slug=kwargs["slug"]) |
|
39 |
consumer_key = self.request.session.get('ovh-token-%s' % kwargs['uuid']) |
|
40 | ||
41 |
if consumer_key: |
|
42 |
connector.consumer_key = consumer_key |
|
43 |
connector.save() |
|
44 |
messages.success(self.request, _('Successfuly completed connector configuration.')) |
|
45 |
else: |
|
46 |
messages.warning(self.request, _('Could not complete connector configuration, please try again.')) |
|
47 | ||
48 |
return connector.get_absolute_url() |
tests/test_sms.py | ||
---|---|---|
1 | 1 |
import isodate |
2 |
import json |
|
2 | 3 |
import mock |
3 | 4 |
import pytest |
4 | 5 |
from requests import RequestException |
5 | 6 | |
7 |
from django.conf import settings |
|
6 | 8 |
from django.contrib.contenttypes.models import ContentType |
7 | 9 |
from django.core.urlresolvers import reverse |
8 | 10 | |
... | ... | |
368 | 370 |
with utils.mock_url(ovh_url, resp, 200) as mocked: |
369 | 371 |
connector.hourly() |
370 | 372 |
assert len(mailoutbox) == 1 |
373 | ||
374 | ||
375 |
def test_ovh_token_request(admin_user, app): |
|
376 |
connector = OVHSMSGateway.objects.create( |
|
377 |
slug='test-ovh', title='Test OVH', account='sms-test42', |
|
378 |
application_key='RHrTdU2oTsrVC0pu', |
|
379 |
application_secret='CLjtS69tTcPgCKxedeoZlgMSoQGSiXMa', |
|
380 |
) |
|
381 | ||
382 |
app = login(app) |
|
383 |
resp = app.get(connector.get_absolute_url()) |
|
384 |
assert 'not operational yet' in resp.text |
|
385 | ||
386 |
ovh_request_token_url = 'https://eu.api.ovh.com/1.0/auth/credential' |
|
387 |
ovh_response = { |
|
388 |
'consumerKey': 'xyz', |
|
389 |
'validationUrl': 'https://eu.api.ovh.com/auth/?credentialToken=iQ1joJE', |
|
390 |
} |
|
391 |
with utils.mock_url(ovh_request_token_url, ovh_response, 302) as mocked: |
|
392 |
resp = resp.click('request access') |
|
393 |
assert resp.url == 'https://eu.api.ovh.com/auth/?credentialToken=iQ1joJE' |
|
394 | ||
395 |
request = mocked.handlers[0].call['requests'][0] |
|
396 |
body = json.loads(request.body) |
|
397 |
assert 'accessRules' in body |
|
398 |
redirect_url = body['redirection'][len(settings.SITE_BASE_URL):] |
|
399 | ||
400 |
resp = app.get(redirect_url).follow() |
|
401 |
assert 'Successfuly completed connector configuration' in resp.text |
|
402 |
connector.refresh_from_db() |
|
403 |
assert connector.consumer_key == 'xyz' |
|
371 |
- |