Projet

Général

Profil

0001-ovh-ease-setup-with-new-API-47851.patch

Valentin Deniaud, 19 octobre 2020 16:07

Télécharger (8,12 ko)

Voir les différences:

Subject: [PATCH] ovh: ease setup with new API (#47851)

 .../ovh/migrations/0012_auto_20201019_1556.py | 25 ++++++++++
 passerelle/apps/ovh/models.py                 |  5 +-
 .../templates/ovh/ovhsmsgateway_detail.html   |  7 +++
 passerelle/apps/ovh/urls.py                   | 10 ++++
 passerelle/apps/ovh/views.py                  | 48 +++++++++++++++++++
 tests/test_sms.py                             | 33 +++++++++++++
 6 files changed, 125 insertions(+), 3 deletions(-)
 create mode 100644 passerelle/apps/ovh/migrations/0012_auto_20201019_1556.py
 create mode 100644 passerelle/apps/ovh/urls.py
 create mode 100644 passerelle/apps/ovh/views.py
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
-