Compare commits
14 Commits
main
...
wip/39092-
Author | SHA1 | Date |
---|---|---|
Frédéric Péters | fbc3c6541f | |
Frédéric Péters | 2b3b7c7707 | |
Frédéric Péters | c73074866b | |
Frédéric Péters | d93570aa87 | |
Frédéric Péters | b3534e1330 | |
Frédéric Péters | 8ccbc23f45 | |
Frédéric Péters | 70bc0df875 | |
Frédéric Péters | fc12e82b09 | |
Frédéric Péters | a67f04b89c | |
Frédéric Péters | f9e22e1309 | |
Frédéric Péters | c434c9e482 | |
Frédéric Péters | ff3f8304bc | |
Frédéric Péters | b2a4754975 | |
Frédéric Péters | 490e418460 |
|
@ -16,7 +16,7 @@ pipeline {
|
||||||
utils.publish_coverage_native('index.html')
|
utils.publish_coverage_native('index.html')
|
||||||
utils.publish_pylint('pylint.out')
|
utils.publish_pylint('pylint.out')
|
||||||
}
|
}
|
||||||
junit '*_results.xml'
|
mergeJunitResults()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# This file is sourced by "execfile" from welco.settings
|
# This file is sourced by "exec(open(..." from welco.settings
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@ -10,12 +10,12 @@ INSTALLED_APPS += ('mellon',)
|
||||||
#
|
#
|
||||||
# hobotization (multitenant)
|
# hobotization (multitenant)
|
||||||
#
|
#
|
||||||
execfile('/usr/lib/hobo/debian_config_common.py')
|
exec(open('/usr/lib/hobo/debian_config_common.py').read())
|
||||||
|
|
||||||
#
|
#
|
||||||
# local settings
|
# local settings
|
||||||
#
|
#
|
||||||
execfile(os.path.join(ETC_DIR, 'settings.py'))
|
exec(open(os.path.join(ETC_DIR, 'settings.py')).read())
|
||||||
|
|
||||||
# run additional settings snippets
|
# run additional settings snippets
|
||||||
execfile('/usr/lib/hobo/debian_config_settings_d.py')
|
exec(open('/usr/lib/hobo/debian_config_settings_d.py').read())
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -112,7 +112,7 @@ setup(
|
||||||
'gadjo',
|
'gadjo',
|
||||||
'django-ckeditor<=4.5.3',
|
'django-ckeditor<=4.5.3',
|
||||||
'django-haystack<2.8',
|
'django-haystack<2.8',
|
||||||
'django-reversion>=2.0',
|
'django-reversion>=2.0,<3',
|
||||||
'django-taggit',
|
'django-taggit',
|
||||||
'djangorestframework>=3.3, <3.7',
|
'djangorestframework>=3.3, <3.7',
|
||||||
'requests',
|
'requests',
|
||||||
|
|
|
@ -19,6 +19,7 @@ import json
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
|
||||||
from httmock import urlmatch, HTTMock
|
from httmock import urlmatch, HTTMock
|
||||||
|
|
||||||
|
@ -50,32 +51,34 @@ class BaseMock(object):
|
||||||
|
|
||||||
class MaarchMock(BaseMock):
|
class MaarchMock(BaseMock):
|
||||||
def list_endpoint(self, url, request):
|
def list_endpoint(self, url, request):
|
||||||
self.requests.append(('list_endpoint', url, request, json.loads(request.body)))
|
self.requests.append(('list_endpoint', url, request, json.loads(force_text(request.body))))
|
||||||
return {
|
return {
|
||||||
'content': json.dumps(self.next_response()),
|
'content': json.dumps(self.next_response()),
|
||||||
'headers': {
|
'headers': {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
},
|
},
|
||||||
|
'status_code': 200,
|
||||||
}
|
}
|
||||||
list_endpoint.path = '^/rest/res/list$'
|
list_endpoint.path = '^/rest/res/list$'
|
||||||
|
|
||||||
def update_external_infos(self, url, request):
|
def update_external_infos(self, url, request):
|
||||||
self.requests.append(('update_external_infos', url, request, json.loads(request.body)))
|
self.requests.append(('update_external_infos', url, request, json.loads(force_text(request.body))))
|
||||||
return json.dumps({})
|
return json.dumps({})
|
||||||
update_external_infos.path = '^/rest/res/externalInfos$'
|
update_external_infos.path = '^/rest/res/externalInfos$'
|
||||||
|
|
||||||
def update_status(self, url, request):
|
def update_status(self, url, request):
|
||||||
self.requests.append(('update_status', url, request, json.loads(request.body)))
|
self.requests.append(('update_status', url, request, json.loads(force_text(request.body))))
|
||||||
return {
|
return {
|
||||||
'content': json.dumps(self.next_response()),
|
'content': json.dumps(self.next_response()),
|
||||||
'headers': {
|
'headers': {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
},
|
},
|
||||||
|
'status_code': 200,
|
||||||
}
|
}
|
||||||
update_status.path = '^/rest/res/resource/status$'
|
update_status.path = '^/rest/res/resource/status$'
|
||||||
|
|
||||||
def post_courrier(self, url, request):
|
def post_courrier(self, url, request):
|
||||||
self.requests.append(('post_courrier', url, request, json.loads(request.body)))
|
self.requests.append(('post_courrier', url, request, json.loads(force_text(request.body))))
|
||||||
post_courrier.path = '^/rest/res$'
|
post_courrier.path = '^/rest/res$'
|
||||||
|
|
||||||
|
|
||||||
|
@ -152,7 +155,7 @@ def test_utils(maarch):
|
||||||
assert welco_maarch_obj.grc_refused_status == 'GRCREFUSED'
|
assert welco_maarch_obj.grc_refused_status == 'GRCREFUSED'
|
||||||
|
|
||||||
|
|
||||||
PDF_MOCK = '%PDF-1.4 ...'
|
PDF_MOCK = b'%PDF-1.4 ...'
|
||||||
|
|
||||||
|
|
||||||
def test_feed(settings, app, maarch, wcs, user):
|
def test_feed(settings, app, maarch, wcs, user):
|
||||||
|
@ -173,7 +176,7 @@ def test_feed(settings, app, maarch, wcs, user):
|
||||||
'resources': [
|
'resources': [
|
||||||
{
|
{
|
||||||
'res_id': 1,
|
'res_id': 1,
|
||||||
'fileBase64Content': base64.b64encode(PDF_MOCK),
|
'fileBase64Content': force_text(base64.b64encode(PDF_MOCK)),
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
|
@ -250,7 +253,7 @@ def test_feed(settings, app, maarch, wcs, user):
|
||||||
user.set_password('test')
|
user.set_password('test')
|
||||||
user.save()
|
user.save()
|
||||||
# verify authentication error
|
# verify authentication error
|
||||||
response = app.post_json('/api/mail/response/', params={}, status=403)
|
response = app.post_json('/api/mail/response/', params={}, status=(401, 403))
|
||||||
app.authorization = ('Basic', ('test', 'test'))
|
app.authorization = ('Basic', ('test', 'test'))
|
||||||
# verify serializer error
|
# verify serializer error
|
||||||
response = app.post_json('/api/mail/response/', params={}, status=400)
|
response = app.post_json('/api/mail/response/', params={}, status=400)
|
||||||
|
|
|
@ -21,6 +21,8 @@ import pytest
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
from django.utils import six
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.timezone import now, timedelta
|
from django.utils.timezone import now, timedelta
|
||||||
|
|
||||||
from welco.sources.phone import models
|
from welco.sources.phone import models
|
||||||
|
@ -42,7 +44,7 @@ def test_call_start_stop(client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneCall.objects.count() == 1
|
assert models.PhoneCall.objects.count() == 1
|
||||||
assert models.PhoneCall.objects.filter(
|
assert models.PhoneCall.objects.filter(
|
||||||
caller='0033699999999',
|
caller='0033699999999',
|
||||||
|
@ -53,7 +55,7 @@ def test_call_start_stop(client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneCall.objects.count() == 2
|
assert models.PhoneCall.objects.count() == 2
|
||||||
assert models.PhoneCall.objects.filter(
|
assert models.PhoneCall.objects.filter(
|
||||||
caller='0033699999999',
|
caller='0033699999999',
|
||||||
|
@ -69,7 +71,7 @@ def test_call_start_stop(client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneCall.objects.count() == 2
|
assert models.PhoneCall.objects.count() == 2
|
||||||
assert models.PhoneCall.objects.filter(
|
assert models.PhoneCall.objects.filter(
|
||||||
caller='0033699999999',
|
caller='0033699999999',
|
||||||
|
@ -80,7 +82,7 @@ def test_call_start_stop(client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneCall.objects.count() == 2
|
assert models.PhoneCall.objects.count() == 2
|
||||||
assert models.PhoneCall.objects.filter(
|
assert models.PhoneCall.objects.filter(
|
||||||
caller='0033699999999',
|
caller='0033699999999',
|
||||||
|
@ -140,7 +142,7 @@ def test_current_calls(user, client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
|
|
||||||
# register user to some lines
|
# register user to some lines
|
||||||
# then remove from some
|
# then remove from some
|
||||||
|
@ -152,7 +154,7 @@ def test_current_calls(user, client):
|
||||||
response = client.get(reverse('phone-current-calls'))
|
response = client.get(reverse('phone-current-calls'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
payload = json.loads(response.content)
|
payload = response.json()
|
||||||
assert isinstance(payload, dict)
|
assert isinstance(payload, dict)
|
||||||
assert set(payload.keys()) == set(['err', 'data'])
|
assert set(payload.keys()) == set(['err', 'data'])
|
||||||
assert payload['err'] == 0
|
assert payload['err'] == 0
|
||||||
|
@ -166,13 +168,13 @@ def test_current_calls(user, client):
|
||||||
assert len(data['all-lines']) == 10
|
assert len(data['all-lines']) == 10
|
||||||
for call in data['calls']:
|
for call in data['calls']:
|
||||||
assert set(call.keys()) <= set(['caller', 'callee', 'start', 'data'])
|
assert set(call.keys()) <= set(['caller', 'callee', 'start', 'data'])
|
||||||
assert isinstance(call['caller'], unicode)
|
assert isinstance(call['caller'], six.string_types)
|
||||||
assert isinstance(call['callee'], unicode)
|
assert isinstance(call['callee'], six.string_types)
|
||||||
assert isinstance(call['start'], unicode)
|
assert isinstance(call['start'], six.string_types)
|
||||||
if 'data' in call:
|
if 'data' in call:
|
||||||
assert isinstance(call['data'], dict)
|
assert isinstance(call['data'], dict)
|
||||||
assert len([call for call in data['lines'] if isinstance(call, unicode)]) == 5
|
assert len([call for call in data['lines'] if isinstance(call, six.string_types)]) == 5
|
||||||
assert len([call for call in data['all-lines'] if isinstance(call, unicode)]) == 10
|
assert len([call for call in data['all-lines'] if isinstance(call, six.string_types)]) == 10
|
||||||
|
|
||||||
# unregister user to all remaining lines
|
# unregister user to all remaining lines
|
||||||
for number in range(0, 5):
|
for number in range(0, 5):
|
||||||
|
@ -180,7 +182,7 @@ def test_current_calls(user, client):
|
||||||
response = client.get(reverse('phone-current-calls'))
|
response = client.get(reverse('phone-current-calls'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
payload = json.loads(response.content)
|
payload = response.json()
|
||||||
assert isinstance(payload, dict)
|
assert isinstance(payload, dict)
|
||||||
assert set(payload.keys()) == set(['err', 'data'])
|
assert set(payload.keys()) == set(['err', 'data'])
|
||||||
assert payload['err'] == 0
|
assert payload['err'] == 0
|
||||||
|
@ -201,7 +203,7 @@ def test_take_release_line(user, client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneLine.objects.count() == 1
|
assert models.PhoneLine.objects.count() == 1
|
||||||
assert models.PhoneLine.objects.filter(
|
assert models.PhoneLine.objects.filter(
|
||||||
users=user, callee='102').count() == 1
|
users=user, callee='102').count() == 1
|
||||||
|
@ -209,7 +211,7 @@ def test_take_release_line(user, client):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert response['content-type'] == 'application/json'
|
assert response['content-type'] == 'application/json'
|
||||||
assert json.loads(response.content) == {'err': 0}
|
assert response.json() == {'err': 0}
|
||||||
assert models.PhoneLine.objects.count() == 1
|
assert models.PhoneLine.objects.count() == 1
|
||||||
assert models.PhoneLine.objects.filter(
|
assert models.PhoneLine.objects.filter(
|
||||||
users=user, callee='102').count() == 0
|
users=user, callee='102').count() == 0
|
||||||
|
@ -219,18 +221,18 @@ def test_phone_zone(user, client):
|
||||||
client.login(username='toto', password='toto')
|
client.login(username='toto', password='toto')
|
||||||
response = client.get(reverse('phone-zone'))
|
response = client.get(reverse('phone-zone'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert 'You do not have a phoneline configured' in response.content
|
assert 'You do not have a phoneline configured' in force_text(response.content)
|
||||||
|
|
||||||
models.PhoneLine.take(callee='102', user=user)
|
models.PhoneLine.take(callee='102', user=user)
|
||||||
|
|
||||||
response = client.get(reverse('phone-zone'))
|
response = client.get(reverse('phone-zone'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert 'You do not have a phoneline configured' not in response.content
|
assert 'You do not have a phoneline configured' not in force_text(response.content)
|
||||||
assert '<li>102' in response.content
|
assert '<li>102' in force_text(response.content)
|
||||||
assert 'data-callee="102"' in response.content
|
assert 'data-callee="102"' in force_text(response.content)
|
||||||
currents = re.search('<div id="source-mainarea" '
|
currents = re.search('<div id="source-mainarea" '
|
||||||
'data-current-calls="/api/phone/current-calls/">'
|
'data-current-calls="/api/phone/current-calls/">'
|
||||||
'(.*?)</div>', response.content, flags=re.DOTALL)
|
'(.*?)</div>', force_text(response.content), flags=re.DOTALL)
|
||||||
assert currents.group(1).strip() == ''
|
assert currents.group(1).strip() == ''
|
||||||
|
|
||||||
# create a call
|
# create a call
|
||||||
|
@ -240,7 +242,7 @@ def test_phone_zone(user, client):
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
response = client.get(reverse('phone-zone'))
|
response = client.get(reverse('phone-zone'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert '<h1>Current Call: <strong>003369999999</strong></h1>' in response.content
|
assert '<h1>Current Call: <strong>003369999999</strong></h1>' in force_text(response.content)
|
||||||
|
|
||||||
# simulate a mellon user
|
# simulate a mellon user
|
||||||
session = client.session
|
session = client.session
|
||||||
|
@ -248,19 +250,19 @@ def test_phone_zone(user, client):
|
||||||
session.save()
|
session.save()
|
||||||
response = client.get(reverse('phone-zone'))
|
response = client.get(reverse('phone-zone'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert 'agent007' not in response.content
|
assert 'agent007' not in force_text(response.content)
|
||||||
assert 'data-callee="agent007"' not in response.content
|
assert 'data-callee="agent007"' not in force_text(response.content)
|
||||||
assert '<li>102' in response.content
|
assert '<li>102' in force_text(response.content)
|
||||||
assert 'data-callee="102"' in response.content
|
assert 'data-callee="102"' in force_text(response.content)
|
||||||
|
|
||||||
with override_settings(PHONE_AUTOTAKE_MELLON_USERNAME=True):
|
with override_settings(PHONE_AUTOTAKE_MELLON_USERNAME=True):
|
||||||
response = client.get(reverse('phone-zone'))
|
response = client.get(reverse('phone-zone'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
assert '<h1>Current Call: <strong>003369999999</strong></h1>' in response.content
|
assert '<h1>Current Call: <strong>003369999999</strong></h1>' in force_text(response.content)
|
||||||
assert 'agent007' in response.content
|
assert 'agent007' in force_text(response.content)
|
||||||
assert 'data-callee="agent007"' in response.content
|
assert 'data-callee="agent007"' in force_text(response.content)
|
||||||
assert '<li>102' in response.content
|
assert '<li>102' in force_text(response.content)
|
||||||
assert 'data-callee="102"' in response.content
|
assert 'data-callee="102"' in force_text(response.content)
|
||||||
|
|
||||||
|
|
||||||
def test_call_expiration(user, client):
|
def test_call_expiration(user, client):
|
||||||
|
@ -277,7 +279,7 @@ def test_call_expiration(user, client):
|
||||||
client.login(username='toto', password='toto')
|
client.login(username='toto', password='toto')
|
||||||
response = client.get(reverse('phone-current-calls'))
|
response = client.get(reverse('phone-current-calls'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
payload = json.loads(response.content)
|
payload = response.json()
|
||||||
assert payload['err'] == 0
|
assert payload['err'] == 0
|
||||||
assert len(payload['data']['calls']) == 1
|
assert len(payload['data']['calls']) == 1
|
||||||
|
|
||||||
|
@ -288,7 +290,7 @@ def test_call_expiration(user, client):
|
||||||
# get list of calls without expiration
|
# get list of calls without expiration
|
||||||
response = client.get(reverse('phone-current-calls'))
|
response = client.get(reverse('phone-current-calls'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
payload = json.loads(response.content)
|
payload = response.json()
|
||||||
assert payload['err'] == 0
|
assert payload['err'] == 0
|
||||||
assert len(payload['data']['calls']) == 1 # still here
|
assert len(payload['data']['calls']) == 1 # still here
|
||||||
|
|
||||||
|
@ -296,7 +298,7 @@ def test_call_expiration(user, client):
|
||||||
with override_settings(PHONE_MAX_CALL_DURATION=2):
|
with override_settings(PHONE_MAX_CALL_DURATION=2):
|
||||||
response = client.get(reverse('phone-current-calls'))
|
response = client.get(reverse('phone-current-calls'))
|
||||||
assert response.status_code == 200
|
assert response.status_code == 200
|
||||||
payload = json.loads(response.content)
|
payload = response.json()
|
||||||
assert payload['err'] == 0
|
assert payload['err'] == 0
|
||||||
assert len(payload['data']['calls']) == 0 # call is expired
|
assert len(payload['data']['calls']) == 0 # call is expired
|
||||||
|
|
||||||
|
|
13
tox.ini
13
tox.ini
|
@ -1,6 +1,6 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = py27-django111
|
envlist = py27-django111-coverage-pylint,py3-django111
|
||||||
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/welco/
|
toxworkdir = {env:TMPDIR:/tmp}/tox-{env:USER}/welco/{env:BRANCH_NAME:}
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
usedevelop =
|
usedevelop =
|
||||||
|
@ -9,12 +9,13 @@ setenv =
|
||||||
DJANGO_SETTINGS_MODULE=welco.settings
|
DJANGO_SETTINGS_MODULE=welco.settings
|
||||||
WELCO_SETTINGS_FILE=tests/settings.py
|
WELCO_SETTINGS_FILE=tests/settings.py
|
||||||
fast: FAST=--nomigrations
|
fast: FAST=--nomigrations
|
||||||
|
coverage: COVERAGE=--junitxml=junit-{envname}.xml --cov-report xml --cov-report html --cov=welco/
|
||||||
deps =
|
deps =
|
||||||
django111: django>=1.11,<1.12
|
django111: django>=1.11,<1.12
|
||||||
pytest-cov
|
pytest-cov
|
||||||
pytest-django
|
pytest-django
|
||||||
pytest<4.1
|
pytest!=5.3.3
|
||||||
attrs<19.2
|
attrs
|
||||||
WebTest
|
WebTest
|
||||||
mock
|
mock
|
||||||
httmock
|
httmock
|
||||||
|
@ -26,5 +27,5 @@ deps =
|
||||||
lxml
|
lxml
|
||||||
git+https://git.entrouvert.org/debian/django-ckeditor.git
|
git+https://git.entrouvert.org/debian/django-ckeditor.git
|
||||||
commands =
|
commands =
|
||||||
django111: ./pylint.sh welco/
|
pylint: ./pylint.sh welco/
|
||||||
django111: py.test {posargs: --junitxml=test_{envname}_results.xml --cov-report xml --cov-report html --cov=welco/ tests/}
|
py.test {env:COVERAGE:} {posargs:tests/}
|
||||||
|
|
|
@ -14,9 +14,8 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from HTMLParser import HTMLParser
|
|
||||||
|
|
||||||
from django.utils.html import strip_tags
|
from django.utils.html import strip_tags
|
||||||
|
from django.utils.six.moves.html_parser import HTMLParser
|
||||||
|
|
||||||
from haystack import indexes
|
from haystack import indexes
|
||||||
|
|
||||||
|
|
|
@ -220,4 +220,4 @@ REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ['rest_framework.authenticati
|
||||||
local_settings_file = os.environ.get('WELCO_SETTINGS_FILE',
|
local_settings_file = os.environ.get('WELCO_SETTINGS_FILE',
|
||||||
os.path.join(os.path.dirname(__file__), 'local_settings.py'))
|
os.path.join(os.path.dirname(__file__), 'local_settings.py'))
|
||||||
if os.path.exists(local_settings_file):
|
if os.path.exists(local_settings_file):
|
||||||
execfile(local_settings_file)
|
exec(open(local_settings_file).read())
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import urlparse
|
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
from dateutil.parser import parse as parse_datetime
|
from dateutil.parser import parse as parse_datetime
|
||||||
|
from django.utils import six
|
||||||
|
from django.utils.six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
|
@ -87,8 +88,8 @@ class MaarchCourrier(object):
|
||||||
excluded_keys = ['content', 'format', 'status', 'maarch_courrier', 'pk']
|
excluded_keys = ['content', 'format', 'status', 'maarch_courrier', 'pk']
|
||||||
data = {key: self.__dict__[key] for key in self.__dict__ if key not in excluded_keys}
|
data = {key: self.__dict__[key] for key in self.__dict__ if key not in excluded_keys}
|
||||||
if data:
|
if data:
|
||||||
for key, value in data.iteritems():
|
for key, value in data.items():
|
||||||
if isinstance(value, basestring):
|
if isinstance(value, six.string_types):
|
||||||
d.append({'column': key, 'value': value, 'type': 'string'})
|
d.append({'column': key, 'value': value, 'type': 'string'})
|
||||||
elif isinstance(value, int):
|
elif isinstance(value, int):
|
||||||
d.append({'column': key, 'value': str(value), 'type': 'int'})
|
d.append({'column': key, 'value': str(value), 'type': 'int'})
|
||||||
|
|
|
@ -24,6 +24,8 @@ from django.template import RequestContext
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpResponseBadRequest, HttpResponse
|
from django.http import HttpResponseBadRequest, HttpResponse
|
||||||
|
from django.utils import six
|
||||||
|
from django.utils.encoding import force_text
|
||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
|
||||||
|
@ -83,20 +85,20 @@ def call_event(request):
|
||||||
'''
|
'''
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
try:
|
try:
|
||||||
payload = json.loads(request.body)
|
payload = json.loads(force_text(request.body))
|
||||||
assert isinstance(payload, dict), 'payload is not a JSON object'
|
assert isinstance(payload, dict), 'payload is not a JSON object'
|
||||||
assert set(payload.keys()) <= set(['event', 'caller', 'callee', 'data']), \
|
assert set(payload.keys()) <= set(['event', 'caller', 'callee', 'data']), \
|
||||||
'payload keys must be "event", "caller", "callee" and optionnaly "data"'
|
'payload keys must be "event", "caller", "callee" and optionnaly "data"'
|
||||||
assert set(['event', 'caller', 'callee']) <= set(payload.keys()), \
|
assert set(['event', 'caller', 'callee']) <= set(payload.keys()), \
|
||||||
'payload keys must be "event", "caller", "callee" and optionnaly "data"'
|
'payload keys must be "event", "caller", "callee" and optionnaly "data"'
|
||||||
assert payload['event'] in ('start', 'stop'), 'event must be "start" or "stop"'
|
assert payload['event'] in ('start', 'stop'), 'event must be "start" or "stop"'
|
||||||
assert isinstance(payload['caller'], unicode), 'caller must be a string'
|
assert isinstance(payload['caller'], six.string_types), 'caller must be a string'
|
||||||
assert isinstance(payload['callee'], unicode), 'callee must be a string'
|
assert isinstance(payload['callee'], six.string_types), 'callee must be a string'
|
||||||
if 'data' in payload:
|
if 'data' in payload:
|
||||||
assert isinstance(payload['data'], dict), 'data must be a JSON object'
|
assert isinstance(payload['data'], dict), 'data must be a JSON object'
|
||||||
except (TypeError, ValueError, AssertionError), e:
|
except (TypeError, ValueError, AssertionError) as e:
|
||||||
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
||||||
unicode(e)}),
|
force_text(e)}),
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
# janitoring: stop active calls to the callee
|
# janitoring: stop active calls to the callee
|
||||||
if settings.PHONE_ONE_CALL_PER_CALLEE:
|
if settings.PHONE_ONE_CALL_PER_CALLEE:
|
||||||
|
@ -196,12 +198,12 @@ def take_line(request):
|
||||||
'''
|
'''
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
try:
|
try:
|
||||||
payload = json.loads(request.body)
|
payload = json.loads(force_text(request.body))
|
||||||
assert isinstance(payload, dict), 'payload is not a JSON object'
|
assert isinstance(payload, dict), 'payload is not a JSON object'
|
||||||
assert payload.keys() == ['callee'], 'payload must have only one key: callee'
|
assert list(payload.keys()) == ['callee'], 'payload must have only one key: callee'
|
||||||
except (TypeError, ValueError, AssertionError), e:
|
except (TypeError, ValueError, AssertionError) as e:
|
||||||
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
||||||
unicode(e)}),
|
force_text(e)}),
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
PhoneLine.take(payload['callee'], request.user)
|
PhoneLine.take(payload['callee'], request.user)
|
||||||
logger.info(u'user %s took line %s', request.user, payload['callee'])
|
logger.info(u'user %s took line %s', request.user, payload['callee'])
|
||||||
|
@ -217,12 +219,12 @@ def release_line(request):
|
||||||
'''
|
'''
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
try:
|
try:
|
||||||
payload = json.loads(request.body)
|
payload = json.loads(force_text(request.body))
|
||||||
assert isinstance(payload, dict), 'payload is not a JSON object'
|
assert isinstance(payload, dict), 'payload is not a JSON object'
|
||||||
assert payload.keys() == ['callee'], 'payload must have only one key: callee'
|
assert list(payload.keys()) == ['callee'], 'payload must have only one key: callee'
|
||||||
except (TypeError, ValueError, AssertionError), e:
|
except (TypeError, ValueError, AssertionError) as e:
|
||||||
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
|
||||||
unicode(e)}),
|
force_text(e)}),
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
PhoneLine.release(payload['callee'], request.user)
|
PhoneLine.release(payload['callee'], request.user)
|
||||||
logger.info(u'user %s released line %s', request.user, payload['callee'])
|
logger.info(u'user %s released line %s', request.user, payload['callee'])
|
||||||
|
|
|
@ -22,13 +22,14 @@ import json
|
||||||
import random
|
import random
|
||||||
import re
|
import re
|
||||||
import requests
|
import requests
|
||||||
import urllib
|
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.http import HttpResponse, HttpResponseBadRequest
|
from django.http import HttpResponse, HttpResponseBadRequest
|
||||||
from django.utils.http import urlencode
|
from django.utils.encoding import smart_bytes
|
||||||
|
from django.utils.http import urlencode, quote
|
||||||
|
from django.utils.six.moves.urllib import parse as urlparse
|
||||||
|
|
||||||
|
|
||||||
def sign_url(url, key, algo='sha256', timestamp=None, nonce=None):
|
def sign_url(url, key, algo='sha256', timestamp=None, nonce=None):
|
||||||
parsed = urlparse.urlparse(url)
|
parsed = urlparse.urlparse(url)
|
||||||
|
@ -44,17 +45,17 @@ def sign_query(query, key, algo='sha256', timestamp=None, nonce=None):
|
||||||
new_query = query
|
new_query = query
|
||||||
if new_query:
|
if new_query:
|
||||||
new_query += '&'
|
new_query += '&'
|
||||||
new_query += urllib.urlencode((
|
new_query += urlencode((
|
||||||
('algo', algo),
|
('algo', algo),
|
||||||
('timestamp', timestamp),
|
('timestamp', timestamp),
|
||||||
('nonce', nonce)))
|
('nonce', nonce)))
|
||||||
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
|
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
|
||||||
new_query += '&signature=' + urllib.quote(signature)
|
new_query += '&signature=' + quote(signature)
|
||||||
return new_query
|
return new_query
|
||||||
|
|
||||||
def sign_string(s, key, algo='sha256', timedelta=30):
|
def sign_string(s, key, algo='sha256', timedelta=30):
|
||||||
digestmod = getattr(hashlib, algo)
|
digestmod = getattr(hashlib, algo)
|
||||||
hash = hmac.HMAC(str(key), digestmod=digestmod, msg=s)
|
hash = hmac.HMAC(smart_bytes(key), digestmod=digestmod, msg=smart_bytes(s))
|
||||||
return hash.digest()
|
return hash.digest()
|
||||||
|
|
||||||
def get_wcs_services():
|
def get_wcs_services():
|
||||||
|
@ -78,7 +79,7 @@ def get_wcs_json(wcs_url, path, wcs_site, params={}):
|
||||||
|
|
||||||
def get_wcs_options(url, condition=None, params={}):
|
def get_wcs_options(url, condition=None, params={}):
|
||||||
categories = {}
|
categories = {}
|
||||||
for wcs_key, wcs_site in get_wcs_services().iteritems():
|
for wcs_key, wcs_site in get_wcs_services().items():
|
||||||
site_title = wcs_site.get('title')
|
site_title = wcs_site.get('title')
|
||||||
response_json = get_wcs_json(wcs_site.get('url'), url, wcs_site, params)
|
response_json = get_wcs_json(wcs_site.get('url'), url, wcs_site, params)
|
||||||
if type(response_json) is dict:
|
if type(response_json) is dict:
|
||||||
|
@ -99,7 +100,7 @@ def get_wcs_options(url, condition=None, params={}):
|
||||||
categories[category_key].append((reference, title))
|
categories[category_key].append((reference, title))
|
||||||
options = []
|
options = []
|
||||||
for category in sorted(categories.keys()):
|
for category in sorted(categories.keys()):
|
||||||
options.append((category, sorted(categories[category], lambda x, y: cmp(x[1], y[1]))))
|
options.append((category, sorted(categories[category], key=lambda x: x[1])))
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def get_wcs_formdef_details(formdef_reference):
|
def get_wcs_formdef_details(formdef_reference):
|
||||||
|
@ -134,7 +135,7 @@ def push_wcs_formdata(request, formdef_reference, context=None):
|
||||||
if request.session.get('mellon_session'):
|
if request.session.get('mellon_session'):
|
||||||
mellon = request.session['mellon_session']
|
mellon = request.session['mellon_session']
|
||||||
nameid = mellon['name_id_content']
|
nameid = mellon['name_id_content']
|
||||||
url += '&NameID=' + urllib.quote(nameid)
|
url += '&NameID=' + quote(nameid)
|
||||||
|
|
||||||
url = sign_url(url, wcs_site.get('secret'))
|
url = sign_url(url, wcs_site.get('secret'))
|
||||||
|
|
||||||
|
@ -153,17 +154,12 @@ def get_wcs_data(endpoint, params=None):
|
||||||
wcs_site_url += '/'
|
wcs_site_url += '/'
|
||||||
url = wcs_site_url + endpoint
|
url = wcs_site_url + endpoint
|
||||||
|
|
||||||
if params:
|
if not params:
|
||||||
params = params.copy()
|
|
||||||
for param, value in params.items():
|
|
||||||
if isinstance(value, unicode):
|
|
||||||
params[param] = value.encode('utf-8')
|
|
||||||
else:
|
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
params['orig'] = wcs_site.get('orig')
|
params['orig'] = wcs_site.get('orig')
|
||||||
if params:
|
if params:
|
||||||
url += '?' + urllib.urlencode(params.items())
|
url += '?' + urlencode(params.items())
|
||||||
url = sign_url(url, wcs_site.get('secret'))
|
url = sign_url(url, wcs_site.get('secret'))
|
||||||
|
|
||||||
response = requests.get(url)
|
response = requests.get(url)
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import urllib
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import logout as auth_logout
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
@ -29,6 +28,7 @@ from django.shortcuts import resolve_url
|
||||||
from django import template
|
from django import template
|
||||||
from django.template import RequestContext
|
from django.template import RequestContext
|
||||||
from django.utils.encoding import force_text
|
from django.utils.encoding import force_text
|
||||||
|
from django.utils.http import quote
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.views.decorators.csrf import csrf_exempt
|
from django.views.decorators.csrf import csrf_exempt
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
@ -38,9 +38,9 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
get_idps = lambda: []
|
get_idps = lambda: []
|
||||||
|
|
||||||
from sources.mail.views import Home as MailHome
|
from .sources.mail.views import Home as MailHome
|
||||||
from sources.phone.views import Home as PhoneHome
|
from .sources.phone.views import Home as PhoneHome
|
||||||
from sources.counter.views import Home as CounterHome
|
from .sources.counter.views import Home as CounterHome
|
||||||
from .qualif.models import Association
|
from .qualif.models import Association
|
||||||
from .kb.views import HomeZone as KbHomeZone, check_user_perms as check_kb_user_perms
|
from .kb.views import HomeZone as KbHomeZone, check_user_perms as check_kb_user_perms
|
||||||
from .contacts.views import HomeZone as ContactsHomeZone
|
from .contacts.views import HomeZone as ContactsHomeZone
|
||||||
|
@ -52,7 +52,7 @@ def login(request, *args, **kwargs):
|
||||||
if not 'next' in request.GET:
|
if not 'next' in request.GET:
|
||||||
return HttpResponseRedirect(resolve_url('mellon_login'))
|
return HttpResponseRedirect(resolve_url('mellon_login'))
|
||||||
return HttpResponseRedirect(resolve_url('mellon_login') + '?next='
|
return HttpResponseRedirect(resolve_url('mellon_login') + '?next='
|
||||||
+ urllib.quote(request.GET.get('next')))
|
+ quote(request.GET.get('next')))
|
||||||
return auth_views.login(request, *args, **kwargs)
|
return auth_views.login(request, *args, **kwargs)
|
||||||
|
|
||||||
def logout(request, next_page=None):
|
def logout(request, next_page=None):
|
||||||
|
@ -180,7 +180,7 @@ def create_formdata(request, *args, **kwargs):
|
||||||
qualif = Association.objects.get(id=kwargs.get('pk'))
|
qualif = Association.objects.get(id=kwargs.get('pk'))
|
||||||
try:
|
try:
|
||||||
qualif.push(request)
|
qualif.push(request)
|
||||||
except Exception, e:
|
except Exception as e:
|
||||||
json.dump({'err': 1, 'msg': str(e)}, response)
|
json.dump({'err': 1, 'msg': str(e)}, response)
|
||||||
return response
|
return response
|
||||||
json.dump({'result': 'ok', 'url': qualif.formdata_url}, response)
|
json.dump({'result': 'ok', 'url': qualif.formdata_url}, response)
|
||||||
|
|
Loading…
Reference in New Issue