Projet

Général

Profil

0001-orange-add-an-option-to-pass-sender-name-56345.patch

Nicolas Roche, 25 août 2021 17:05

Télécharger (8,16 ko)

Voir les différences:

Subject: [PATCH] orange: add an option to pass sender name (#56345)

 .../0010_orangesmsgateway_provide_sender.py   | 22 ++++++++++++++
 passerelle/apps/orange/models.py              | 13 +++++++--
 tests/test_orange.py                          | 29 ++++++++++++++++---
 3 files changed, 58 insertions(+), 6 deletions(-)
 create mode 100644 passerelle/apps/orange/migrations/0010_orangesmsgateway_provide_sender.py
passerelle/apps/orange/migrations/0010_orangesmsgateway_provide_sender.py
1
# Generated by Django 2.2.19 on 2021-08-24 14:30
2

  
3
from django.db import migrations, models
4

  
5

  
6
class Migration(migrations.Migration):
7

  
8
    dependencies = [
9
        ('orange', '0009_auto_20210202_1304'),
10
    ]
11

  
12
    operations = [
13
        migrations.AddField(
14
            model_name='orangesmsgateway',
15
            name='provide_sender',
16
            field=models.BooleanField(
17
                default=False,
18
                help_text='Sender name must be allowed by orange',
19
                verbose_name='Use sender configurated with Publik',
20
            ),
21
        ),
22
    ]
passerelle/apps/orange/models.py
44 44

  
45 45
class OrangeSMSGateway(SMSResource):
46 46
    hide_description_fields = ['groupname']
47 47

  
48 48
    username = models.CharField(verbose_name=_('Identifier'), max_length=64)
49 49
    password = models.CharField(verbose_name=_('Password'), max_length=64)
50 50
    groupname = models.CharField(verbose_name=_('Group'), max_length=64)
51 51

  
52
    provide_sender = models.BooleanField(
53
        _('Use sender configurated with Publik'),
54
        default=False,
55
        help_text=_('Sender name must be allowed by orange'),
56
    )
57

  
52 58
    class Meta:
53 59
        verbose_name = _('Orange')
54 60
        db_table = 'sms_orange'
55 61

  
56 62
    def get_access_token(self):
57 63
        headers = {'content-type': 'application/x-www-form-urlencoded'}
58 64
        params = {'username': self.username, 'password': self.password}
59 65
        response = self.requests.post(URL_TOKEN, data=params, headers=headers)
......
74 80
        for group in response_json:
75 81
            if group['name'] == self.groupname:
76 82
                group_id = group['id']
77 83
                break
78 84
        if not group_id:
79 85
            raise APIError('Group name not found: ' + self.groupname)
80 86
        return group_id
81 87

  
82
    def diffusion(self, access_token, group_id, destinations, message):
88
    def diffusion(self, access_token, group_id, destinations, message, sender):
83 89
        headers = {
84 90
            'content-type': 'application/json',
85 91
            'authorization': 'Bearer %s' % access_token,
86 92
        }
87 93
        payload = {
88 94
            'name': 'Send a SMS from passerelle',
89 95
            'msisdns': destinations,
90 96
            'smsParam': {'encoding': 'GSM7', 'body': message},
91 97
        }
98
        if self.provide_sender:
99
            payload['smsParam']['senderName'] = sender
92 100
        response = self.requests.post(URL_DIFFUSION % group_id, json=payload, headers=headers)
93 101
        if response.status_code != 201:
94 102
            raise OrangeError('Orange fails to send SMS: %s, %s' % (response.status_code, response.text))
95 103
        return get_json(response)
96 104

  
97 105
    def send_msg(self, text, sender, destinations, **kwargs):
98 106
        '''Send a SMS using the Orange provider'''
99 107

  
100 108
        access_token = self.get_access_token()
101 109
        group_id = self.group_id_from_name(access_token)
102
        response = self.diffusion(access_token, group_id, destinations, text)
110
        response = self.diffusion(access_token, group_id, destinations, text, sender)
111
        print(response)
103 112
        return response
tests/test_orange.py
25 25
from passerelle.apps.orange.models import OrangeError, OrangeSMSGateway
26 26
from passerelle.base.models import AccessRight, ApiUser, Job
27 27
from passerelle.utils.jsonresponse import APIError
28 28

  
29 29
NETLOC = 'contact-everyone.orange-business.com'
30 30
JSON_HEADERS = {'content-type': 'application/json'}
31 31
PAYLOAD = {
32 32
    'message': 'hello',
33
    'from': '+33699999999',
33
    'from': 'john',
34 34
    'to': ['+33688888888', '+33677777777'],
35 35
}
36 36

  
37 37

  
38 38
@httmock.urlmatch(netloc=NETLOC, path='/api/v1.2/oauth/token', method='POST')
39 39
def response_token_ok(url, request):
40 40
    assert 'username=jdoe' in request.body
41 41
    assert 'password=secret' in request.body
......
54 54
    return httmock.response(200, content, JSON_HEADERS)
55 55

  
56 56

  
57 57
@httmock.urlmatch(netloc=NETLOC, path='/api/v1.2/groups/gid2/diffusion-requests', method='POST')
58 58
def response_diffusion_ok(url, request):
59 59
    assert request.headers['authorization'] == 'Bearer my_token'
60 60
    request_body = json.loads(force_text(request.body))
61 61
    assert request_body['smsParam']['body'] == PAYLOAD['message']
62
    assert 'senderName' not in request_body['smsParam'].keys()
62 63
    '33688888888' in request_body['msisdns'][0]
63 64
    '33677777777' in request_body['msisdns'][1]
64 65
    content = json.dumps({'status': "I'm ok"})
65 66
    return httmock.response(201, content, JSON_HEADERS)
66 67

  
67 68

  
68 69
@httmock.urlmatch(netloc=NETLOC)
69 70
def response_500(url, request):
......
142 143
    with pytest.raises(OrangeError, match='Orange returned Invalid JSON content'):
143 144
        with httmock.HTTMock(response_invalid_json):
144 145
            orange.group_id_from_name('my_token')
145 146

  
146 147

  
147 148
def test_diffusion(app, connector):
148 149
    orange = OrangeSMSGateway()
149 150
    with httmock.HTTMock(response_diffusion_ok):
150
        resp = orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'])
151
        resp = orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from'])
151 152
    assert resp['status'] == "I'm ok"
152 153

  
153 154
    # not 201
154 155
    with pytest.raises(OrangeError, match='Orange fails to send SMS'):
155 156
        with httmock.HTTMock(response_500):
156
            orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'])
157
            orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from'])
157 158

  
158 159
    # not json
159 160
    @httmock.urlmatch(netloc=NETLOC)
160 161
    def mocked_response(url, request):
161 162
        return httmock.response(201, 'not a JSON content')
162 163

  
163 164
    with pytest.raises(OrangeError, match='Orange returned Invalid JSON content'):
164 165
        with httmock.HTTMock(mocked_response):
165
            orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'])
166
            orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from'])
167

  
168
    # sender name not allowed
169
    @httmock.urlmatch(netloc=NETLOC)
170
    def mocked_response(url, request):
171
        request_body = json.loads(force_text(request.body))
172
        assert request_body['smsParam']['senderName'] == 'john'
173
        error_response = [
174
            {
175
                'code': 'SenderNameNotAllowed',
176
                'field': 'smsParam.senderName',
177
                'message': 'The given sender name is not allowed.',
178
            }
179
        ]
180
        return httmock.response(400, json.dumps(error_response))
181

  
182
    orange.provide_sender = True
183
    orange.save()
184
    with pytest.raises(OrangeError, match='The given sender name is not allowed.'):
185
        with httmock.HTTMock(mocked_response):
186
            orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from'])
166 187

  
167 188

  
168 189
def test_send_msg(app, connector):
169 190
    url = '/%s/%s/send/' % (connector.get_connector_slug(), connector.slug)
170 191
    assert Job.objects.count() == 0
171 192
    resp = app.post_json(url, params=PAYLOAD, status=200)
172 193
    assert not resp.json['err']
173 194
    assert Job.objects.count() == 1
174
-