0001-orange-invert-sender-checkbox-62336.patch
passerelle/apps/orange/migrations/0011_orangesmsgateway_default_sender.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2022-03-18 16:48 |
|
2 | ||
3 |
from django.db import migrations, models |
|
4 | ||
5 | ||
6 |
class Migration(migrations.Migration): |
|
7 | ||
8 |
dependencies = [ |
|
9 |
('orange', '0010_orangesmsgateway_provide_sender'), |
|
10 |
] |
|
11 | ||
12 |
operations = [ |
|
13 |
migrations.AddField( |
|
14 |
model_name='orangesmsgateway', |
|
15 |
name='default_sender', |
|
16 |
field=models.BooleanField( |
|
17 |
default=True, |
|
18 |
help_text='If unchecked, sender configurated with Publik must also be configurated in Orange backoffice', |
|
19 |
verbose_name='Use sender configurated in Orange backoffice', |
|
20 |
), |
|
21 |
), |
|
22 |
] |
passerelle/apps/orange/migrations/0012_invert_sender_checkbox.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2022-03-18 16:52 |
|
2 | ||
3 |
from django.db import migrations |
|
4 | ||
5 | ||
6 |
def forwards_func(apps, schema_editor): |
|
7 |
OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway') |
|
8 |
for con in OrangeSMSGateway.objects.all(): |
|
9 |
con.default_sender = not con.provide_sender |
|
10 |
con.save() |
|
11 | ||
12 | ||
13 |
def reverse_func(apps, schema_editor): |
|
14 |
OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway') |
|
15 |
for con in OrangeSMSGateway.objects.all(): |
|
16 |
con.provide_sender = not con.default_sender |
|
17 |
con.save() |
|
18 | ||
19 | ||
20 |
class Migration(migrations.Migration): |
|
21 | ||
22 |
dependencies = [ |
|
23 |
('orange', '0011_orangesmsgateway_default_sender'), |
|
24 |
] |
|
25 | ||
26 |
operations = [ |
|
27 |
# invert "sender" checkbox |
|
28 |
migrations.RunPython(forwards_func, reverse_func), |
|
29 |
] |
passerelle/apps/orange/migrations/0013_remove_orangesmsgateway_provide_sender.py | ||
---|---|---|
1 |
# Generated by Django 2.2.19 on 2022-03-18 17:00 |
|
2 | ||
3 |
from django.db import migrations |
|
4 | ||
5 | ||
6 |
class Migration(migrations.Migration): |
|
7 | ||
8 |
dependencies = [ |
|
9 |
('orange', '0012_invert_sender_checkbox'), |
|
10 |
] |
|
11 | ||
12 |
operations = [ |
|
13 |
migrations.RemoveField( |
|
14 |
model_name='orangesmsgateway', |
|
15 |
name='provide_sender', |
|
16 |
), |
|
17 |
] |
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'), |
|
52 |
default_sender = models.BooleanField( |
|
53 |
_('Use sender configurated in Orange backoffice'), |
|
54 |
default=True, |
|
55 |
help_text=_( |
|
56 |
'If unchecked, sender configurated with Publik must also be configurated in Orange backoffice' |
|
57 |
), |
|
56 | 58 |
) |
57 | 59 | |
58 | 60 |
class Meta: |
59 | 61 |
verbose_name = _('Orange') |
60 | 62 |
db_table = 'sms_orange' |
61 | 63 | |
62 | 64 |
def get_access_token(self): |
63 | 65 |
headers = {'content-type': 'application/x-www-form-urlencoded'} |
... | ... | |
90 | 92 |
'content-type': 'application/json', |
91 | 93 |
'authorization': 'Bearer %s' % access_token, |
92 | 94 |
} |
93 | 95 |
payload = { |
94 | 96 |
'name': 'Send a SMS from passerelle', |
95 | 97 |
'msisdns': destinations, |
96 | 98 |
'smsParam': {'encoding': 'GSM7', 'body': message}, |
97 | 99 |
} |
98 |
if self.provide_sender:
|
|
100 |
if not self.default_sender:
|
|
99 | 101 |
payload['smsParam']['senderName'] = sender |
100 | 102 |
response = self.requests.post(URL_DIFFUSION % group_id, json=payload, headers=headers) |
101 | 103 |
if response.status_code != 201: |
102 | 104 |
raise OrangeError('Orange fails to send SMS: %s, %s' % (response.status_code, response.text)) |
103 | 105 |
return get_json(response) |
104 | 106 | |
105 | 107 |
def send_msg(self, text, sender, destinations, **kwargs): |
106 | 108 |
'''Send a SMS using the Orange provider''' |
tests/test_orange.py | ||
---|---|---|
15 | 15 |
# You should have received a copy of the GNU Affero General Public License |
16 | 16 |
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | 17 | |
18 | 18 |
import json |
19 | 19 | |
20 | 20 |
import httmock |
21 | 21 |
import pytest |
22 | 22 |
from django.contrib.contenttypes.models import ContentType |
23 |
from django.db import connection |
|
24 |
from django.db.migrations.executor import MigrationExecutor |
|
23 | 25 |
from django.utils.encoding import force_text |
24 | 26 | |
25 | 27 |
from passerelle.apps.orange.models import OrangeError, OrangeSMSGateway |
26 | 28 |
from passerelle.base.models import AccessRight, ApiUser, Job |
27 | 29 |
from passerelle.utils.jsonresponse import APIError |
28 | 30 | |
29 | 31 |
NETLOC = 'contact-everyone.orange-business.com' |
30 | 32 |
JSON_HEADERS = {'content-type': 'application/json'} |
... | ... | |
174 | 176 |
{ |
175 | 177 |
'code': 'SenderNameNotAllowed', |
176 | 178 |
'field': 'smsParam.senderName', |
177 | 179 |
'message': 'The given sender name is not allowed.', |
178 | 180 |
} |
179 | 181 |
] |
180 | 182 |
return httmock.response(400, json.dumps(error_response)) |
181 | 183 | |
182 |
orange.provide_sender = True
|
|
184 |
orange.default_sender = False
|
|
183 | 185 |
orange.save() |
184 | 186 |
with pytest.raises(OrangeError, match='The given sender name is not allowed.'): |
185 | 187 |
with httmock.HTTMock(mocked_response): |
186 | 188 |
orange.diffusion('my_token', 'gid2', PAYLOAD['to'], PAYLOAD['message'], PAYLOAD['from']) |
187 | 189 | |
188 | 190 | |
189 | 191 |
def test_send_msg(app, connector): |
190 | 192 |
url = '/%s/%s/send/' % (connector.get_connector_slug(), connector.slug) |
... | ... | |
200 | 202 |
resp = app.post_json(url, params=PAYLOAD, status=200) |
201 | 203 |
assert not resp.json['err'] |
202 | 204 |
assert Job.objects.count() == 2 |
203 | 205 |
with httmock.HTTMock(response_token_ok, response_group_ok, response_500): |
204 | 206 |
connector.jobs() |
205 | 207 |
job = Job.objects.all()[1] |
206 | 208 |
assert job.status == 'failed' |
207 | 209 |
assert 'Orange fails to send SMS: 500, my_error' in job.status_details['error_summary'] |
210 | ||
211 | ||
212 |
def test_invert_sender_flag_formward_migration(transactional_db): |
|
213 |
migrate_from = [('orange', '0010_orangesmsgateway_provide_sender'), ('base', '0029_auto_20210202_1627')] |
|
214 |
migrate_to = [('orange', '0013_remove_orangesmsgateway_provide_sender')] |
|
215 | ||
216 |
executor = MigrationExecutor(connection) |
|
217 |
old_apps = executor.loader.project_state(migrate_from).apps |
|
218 |
executor.migrate(migrate_from) |
|
219 | ||
220 |
OrangeSMSGateway = old_apps.get_model('orange', 'OrangeSMSGateway') |
|
221 |
OrangeSMSGateway.objects.create(slug='con1', username='jdoe', password='secret', groupname='group2') |
|
222 |
OrangeSMSGateway.objects.create( |
|
223 |
slug='con2', username='jdoe', password='secret', groupname='group2', provide_sender=True |
|
224 |
) |
|
225 |
assert OrangeSMSGateway.objects.get(slug='con1').provide_sender == False |
|
226 |
assert OrangeSMSGateway.objects.get(slug='con2').provide_sender == True |
|
227 | ||
228 |
# ensure migration fixes state |
|
229 |
executor = MigrationExecutor(connection) |
|
230 |
executor.migrate(migrate_to) |
|
231 |
executor.loader.build_graph() |
|
232 |
apps = executor.loader.project_state(migrate_to).apps |
|
233 | ||
234 |
OrangeSMSGateway = apps.get_model('orange', 'OrangeSMSGateway') |
|
235 |
assert OrangeSMSGateway.objects.get(slug='con1').default_sender == True |
|
236 |
assert OrangeSMSGateway.objects.get(slug='con2').default_sender == False |
|
208 |
- |