summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrédéric Péters <fpeters@entrouvert.com>2021-01-11 19:10:12 (GMT)
committerFrédéric Péters <fpeters@entrouvert.com>2021-01-11 19:10:12 (GMT)
commitce7f2dd5000cf1eb462ae18aeeb5ab66913b452f (patch)
tree34d32e2e0914b7867155b25546cfbec543cdfbd3
parent54aae08cfee8296377390138f8cd2f0efe946888 (diff)
downloadwelco-ce7f2dd5000cf1eb462ae18aeeb5ab66913b452f.zip
welco-ce7f2dd5000cf1eb462ae18aeeb5ab66913b452f.tar.gz
welco-ce7f2dd5000cf1eb462ae18aeeb5ab66913b452f.tar.bz2
trivial: apply black
-rw-r--r--debian/settings.py6
-rw-r--r--setup.py20
-rw-r--r--tests/test_contacts_manager.py70
-rw-r--r--tests/test_mail_manager.py40
-rw-r--r--tests/test_manager.py22
-rw-r--r--tests/test_qualification.py28
-rw-r--r--tests/test_source_maarch.py125
-rw-r--r--tests/test_source_phone.py137
-rw-r--r--welco/apps.py1
-rw-r--r--welco/contacts/forms.py13
-rw-r--r--welco/contacts/views.py26
-rw-r--r--welco/kb/apps.py1
-rw-r--r--welco/kb/forms.py1
-rw-r--r--welco/kb/migrations/0001_initial.py8
-rw-r--r--welco/kb/migrations/0003_page_tags.py8
-rw-r--r--welco/kb/models.py3
-rw-r--r--welco/kb/search_indexes.py1
-rw-r--r--welco/kb/views.py19
-rw-r--r--welco/monkeypatch.py27
-rw-r--r--welco/qualif/migrations/0001_initial.py24
-rw-r--r--welco/qualif/models.py8
-rw-r--r--welco/settings.py35
-rw-r--r--welco/sources/counter/migrations/0001_initial.py8
-rw-r--r--welco/sources/counter/models.py5
-rw-r--r--welco/sources/counter/views.py1
-rw-r--r--welco/sources/mail/__init__.py8
-rw-r--r--welco/sources/mail/forms.py1
-rw-r--r--welco/sources/mail/maarch.py19
-rw-r--r--welco/sources/mail/management/commands/feed_mail.py4
-rw-r--r--welco/sources/mail/management/commands/feed_mail_maarch.py11
-rw-r--r--welco/sources/mail/migrations/0001_initial.py8
-rw-r--r--welco/sources/mail/migrations/0011_mail_reference.py3
-rw-r--r--welco/sources/mail/models.py20
-rw-r--r--welco/sources/mail/urls.py3
-rw-r--r--welco/sources/mail/utils.py22
-rw-r--r--welco/sources/mail/views.py18
-rw-r--r--welco/sources/phone/migrations/0001_initial.py8
-rw-r--r--welco/sources/phone/migrations/0002_auto_20151028_1635.py5
-rw-r--r--welco/sources/phone/models.py20
-rw-r--r--welco/sources/phone/views.py144
-rw-r--r--welco/urls.py33
-rw-r--r--welco/utils.py21
-rw-r--r--welco/views.py46
-rw-r--r--welco/wsgi.py2
44 files changed, 575 insertions, 458 deletions
diff --git a/debian/settings.py b/debian/settings.py
index a7a2c6f..9a397d3 100644
--- a/debian/settings.py
+++ b/debian/settings.py
@@ -16,15 +16,15 @@
DEBUG = False
TEMPLATE_DEBUG = False
-#ADMINS = (
+# ADMINS = (
# # ('User 1', 'watchdog@example.net'),
# # ('User 2', 'janitor@example.net'),
-#)
+# )
# ALLOWED_HOSTS must be correct in production!
# See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
- '*',
+ '*',
]
# Databases
diff --git a/setup.py b/setup.py
index 1567303..30cd11c 100644
--- a/setup.py
+++ b/setup.py
@@ -25,16 +25,18 @@ class eo_sdist(sdist):
def get_version():
- '''Use the VERSION, if absent generates a version with git describe, if not
- tag exists, take 0.0- and add the length of the commit log.
- '''
+ """Use the VERSION, if absent generates a version with git describe, if not
+ tag exists, take 0.0- and add the length of the commit log.
+ """
if os.path.exists('VERSION'):
with open('VERSION', 'r') as v:
return v.read()
if os.path.exists('.git'):
p = subprocess.Popen(
['git', 'describe', '--dirty=.dirty', '--match=v*'],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
result = p.communicate()[0]
if p.returncode == 0:
result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v
@@ -45,9 +47,7 @@ def get_version():
version = result
return version
else:
- return '0.0.post%s' % len(
- subprocess.check_output(
- ['git', 'rev-list', 'HEAD']).splitlines())
+ return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
return '0.0'
@@ -65,6 +65,7 @@ class compile_translations(Command):
curdir = os.getcwd()
try:
from django.core.management import call_command
+
for path, dirs, files in os.walk('welco'):
if 'locale' not in dirs:
continue
@@ -108,7 +109,8 @@ setup(
'Programming Language :: Python',
'Programming Language :: Python :: 2',
],
- install_requires=['django>=1.11,<2.3',
+ install_requires=[
+ 'django>=1.11,<2.3',
'gadjo',
'django-ckeditor<4.5.4',
'django-haystack<2.8',
@@ -118,7 +120,7 @@ setup(
'whoosh',
'XStatic-Select2',
'python-dateutil',
- ],
+ ],
zip_safe=False,
cmdclass={
'build': build,
diff --git a/tests/test_contacts_manager.py b/tests/test_contacts_manager.py
index ad72049..db8e8c2 100644
--- a/tests/test_contacts_manager.py
+++ b/tests/test_contacts_manager.py
@@ -29,14 +29,9 @@ def test_get_contacts_zone_view(app, db):
resp = app.get('/ajax/contacts', status=200)
assert resp.html.find('button')['data-url'] == '/contacts/add/'
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- contact_id='42')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), contact_id='42')
source_type = ContentType.objects.get_for_model(Mail).pk
- resp = app.get(
- '/ajax/contacts',
- params={'source_type': source_type, 'source_pk': mail.pk},
- status=200)
+ resp = app.get('/ajax/contacts', params={'source_type': source_type, 'source_pk': mail.pk}, status=200)
assert resp.html.find('a').text == '...'
assert resp.html.find('a')['data-page-slug'] == '42'
@@ -46,9 +41,8 @@ def test_post_contacts_zone_view(app, db):
assert not mail.contact_id
source_type = ContentType.objects.get_for_model(Mail).pk
resp = app.post(
- '/ajax/contacts',
- params={'source_type': source_type, 'source_pk': mail.pk, 'user_id': 42},
- status=200)
+ '/ajax/contacts', params={'source_type': source_type, 'source_pk': mail.pk, 'user_id': 42}, status=200
+ )
assert resp.text == 'ok'
assert Mail.objects.get(id=mail.pk).contact_id == '42'
@@ -90,20 +84,24 @@ def test_search_json_view(settings, app, user, mail_group):
def response(url, request):
headers = {'content-type': 'application/json'}
content = {
- 'data': [{
- 'user_display_name': 'John Doe',
- 'user_email': 'john@example.net',
- 'user_var_phone': '0123456789',
- 'user_var_mobile': '0612345789',
- 'user_id': '42',
- 'user_roles': [{
- 'name': 'Agent',
- 'text': 'Agent',
- 'slug': 'agent',
- 'id': '8d73434814484aa0b8555ac9c68a9300'
- }],
- }],
- 'err': 0
+ 'data': [
+ {
+ 'user_display_name': 'John Doe',
+ 'user_email': 'john@example.net',
+ 'user_var_phone': '0123456789',
+ 'user_var_mobile': '0612345789',
+ 'user_id': '42',
+ 'user_roles': [
+ {
+ 'name': 'Agent',
+ 'text': 'Agent',
+ 'slug': 'agent',
+ 'id': '8d73434814484aa0b8555ac9c68a9300',
+ }
+ ],
+ }
+ ],
+ 'err': 0,
}
return httmock.response(200, content, headers)
@@ -123,6 +121,7 @@ def test_contact_detail_fragment_view(settings, app, db):
}
}
}
+
@httmock.urlmatch(netloc='wcs.example.net', path='/api/users/42/', method='GET')
def response(url, request):
headers = {'content-type': 'application/json'}
@@ -132,12 +131,9 @@ def test_contact_detail_fragment_view(settings, app, db):
'user_var_phone': '0123456789',
'user_var_mobile': '0612345789',
'user_id': '42',
- 'user_roles': [{
- 'name': 'Agent',
- 'text': 'Agent',
- 'slug': 'agent',
- 'id': '8d73434814484aa0b8555ac9c68a9300'
- }],
+ 'user_roles': [
+ {'name': 'Agent', 'text': 'Agent', 'slug': 'agent', 'id': '8d73434814484aa0b8555ac9c68a9300'}
+ ],
}
return httmock.response(200, content, headers)
@@ -148,15 +144,12 @@ def test_contact_detail_fragment_view(settings, app, db):
assert resp.html.find('li').text == 'Phone: 0123456789'
# unused 'is_pinned_user' context
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- contact_id='42')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), contact_id='42')
source_type = ContentType.objects.get_for_model(Mail).pk
with httmock.HTTMock(response):
resp = app.get(
- '/ajax/contacts/42/',
- params={'source_type': source_type, 'source_pk': mail.pk},
- status=200)
+ '/ajax/contacts/42/', params={'source_type': source_type, 'source_pk': mail.pk}, status=200
+ )
assert resp.html.find('h3').text == 'John Doe'
@@ -183,7 +176,7 @@ def test_post_contact_add_view(mocked_sleep, settings, app, db):
'orig': 'http://welco.example.net/',
'secret': 'xxx',
}
- }
+ },
}
# normal case
@@ -210,7 +203,8 @@ def test_post_contact_add_view(mocked_sleep, settings, app, db):
'first_name': 'John',
'last_name': 'Doe',
},
- status=200)
+ status=200,
+ )
assert resp.content_type == 'application/json'
assert resp.json['data']['user_id'] == '43'
diff --git a/tests/test_mail_manager.py b/tests/test_mail_manager.py
index 242102a..d4b04c9 100644
--- a/tests/test_mail_manager.py
+++ b/tests/test_mail_manager.py
@@ -46,10 +46,7 @@ def test_get_feeder_view(app, user):
def test_post_feeder_view(app, user):
app.set_user(user.username)
- resp = app.post(
- '/mail/feeder/',
- params={'mail': Upload('filename.txt', b'contents')},
- status=302)
+ resp = app.post('/mail/feeder/', params={'mail': Upload('filename.txt', b'contents')}, status=302)
assert resp.location == '/mail/feeder/'
resp = resp.follow()
assert resp.html.find('li', {'class': 'info'}).text == '1 files uploaded successfully.'
@@ -63,27 +60,28 @@ def test_qualification_save_view(settings, app, db):
}
}
}
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- subject='spam')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), subject='spam')
assert not mail.contact_id
source_type = ContentType.objects.get_for_model(Mail).pk
resp = app.post(
'/ajax/qualification-mail-save',
params={'source_type': source_type, 'source_pk': mail.pk, 'subject': 'eggs'},
- status=302)
- assert resp.location == '/ajax/qualification?source_type=%s&source_pk=%s' % (
- source_type, mail.pk)
+ status=302,
+ )
+ assert resp.location == '/ajax/qualification?source_type=%s&source_pk=%s' % (source_type, mail.pk)
@httmock.urlmatch(netloc='wcs.example.net', path='/api/formdefs/', method='GET')
def response_get(url, request):
headers = {'content-type': 'application/json'}
content = {
"err": 0,
- "data": [{
- "title": "Foo",
- "slug": "foo",
- }]}
+ "data": [
+ {
+ "title": "Foo",
+ "slug": "foo",
+ }
+ ],
+ }
return httmock.response(200, content, headers)
with httmock.HTTMock(response_get):
@@ -97,9 +95,7 @@ def test_edit_note_view(app, user):
assert resp.location.startswith('/login/?next=')
app.set_user(user.username)
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- note='spam')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), note='spam')
resp = app.get('/ajax/mail/edit-note/', params={'mail': mail.pk}, status=200)
assert resp.html.find('h2').text == 'Note'
assert resp.html.find('textarea', {'name': 'note'}).text == 'spam'
@@ -123,7 +119,7 @@ def test_note_view(app, user):
def test_reject_view(settings, app, user):
- settings.MAARCH_FEED= {
+ settings.MAARCH_FEED = {
'URL': 'http://maarch.example.net',
'ENABLE': True,
'USERNAME': 'xxx',
@@ -134,9 +130,7 @@ def test_reject_view(settings, app, user):
assert resp.location.startswith('/login/?next=')
app.set_user(user.username)
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- external_id='maarch-42')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), external_id='maarch-42')
@httmock.urlmatch(netloc='maarch.example.net', path='/rest/res/resource/status', method='PUT')
def response_ok(url, request):
@@ -150,9 +144,7 @@ def test_reject_view(settings, app, user):
assert Mail.objects.count() == 0
# errors
- mail = Mail.objects.create(
- content=ContentFile('foo', name='bar.txt'),
- external_id='maarch-42')
+ mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'), external_id='maarch-42')
@httmock.urlmatch(netloc='maarch.example.net', path='/rest/res/resource/status', method='PUT')
def response_error1(url, request):
diff --git a/tests/test_manager.py b/tests/test_manager.py
index 259011a..b760643 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -112,15 +112,11 @@ def test_wcs_summary_view(app, mail_group, user):
mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'))
source_type = ContentType.objects.get_for_model(Mail).pk
- resp = app.get(
- '/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk),
- status=302)
+ resp = app.get('/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk), status=302)
assert resp.location.startswith('/login/?next=')
app.set_user(user.username)
- resp = app.get(
- '/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk),
- status=200)
+ resp = app.get('/ajax/summary/%s/%s/?callback=spam' % (source_type, mail.pk), status=200)
assert resp.content_type == 'application/javascript'
assert 'bar' in resp.text
assert resp.text.startswith('spam({')
@@ -130,8 +126,8 @@ def test_remove_association_view(app, mail_group, user):
mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'))
source_type = ContentType.objects.get_for_model(Mail).pk
association = Association.objects.create(
- source_type=ContentType.objects.get(id=source_type),
- source_pk=mail.pk)
+ source_type=ContentType.objects.get(id=source_type), source_pk=mail.pk
+ )
assert Association.objects.filter(id=association.pk).count() == 1
resp = app.get('/ajax/remove-association/%s' % association.pk, status=302)
@@ -154,8 +150,8 @@ def test_create_formdata_view(settings, app, mail_group, user):
mail = Mail.objects.create(content=ContentFile('foo', name='bar.txt'))
source_type = ContentType.objects.get_for_model(Mail).pk
association = Association.objects.create(
- source_type=ContentType.objects.get(id=source_type),
- source_pk=mail.pk)
+ source_type=ContentType.objects.get(id=source_type), source_pk=mail.pk
+ )
resp = app.get('/ajax/create-formdata/%s' % association.pk, status=302)
assert resp.location.startswith('/login/?next=')
@@ -185,7 +181,8 @@ def test_create_formdata_view(settings, app, mail_group, user):
'data': {
'id': 42,
'backoffice_url': 'http://example.net',
- }}
+ },
+ }
return httmock.response(200, content, headers)
with httmock.HTTMock(response_get, response_post):
@@ -204,8 +201,7 @@ def test_menu_json_view(app, user, mail_group, phone_group, counter_group, kb_gr
app.set_user(user.username)
resp = app.get('/menu.json', status=200)
assert resp.content_type == 'application/json'
- assert sorted([x['label'] for x in resp.json]) == [
- 'Call Center', 'Counter', 'Knowledge Base', 'Mails']
+ assert sorted([x['label'] for x in resp.json]) == ['Call Center', 'Counter', 'Knowledge Base', 'Mails']
resp = app.get('/menu.json?callback=foo', status=200)
assert resp.content_type == 'application/javascript'
diff --git a/tests/test_qualification.py b/tests/test_qualification.py
index e9ef4df..b46091c 100644
--- a/tests/test_qualification.py
+++ b/tests/test_qualification.py
@@ -23,27 +23,25 @@ from welco.forms import QualificationForm
pytestmark = pytest.mark.django_db
-KNOWN_SERVICES = {
- 'wcs': {
- 'eservices': {
- 'url': 'http://localhost/',
- 'title': 'Eservices',
- 'orig': 'welco'
- }
- }
-}
+KNOWN_SERVICES = {'wcs': {'eservices': {'url': 'http://localhost/', 'title': 'Eservices', 'orig': 'welco'}}}
@mock.patch('welco.utils.requests.get')
def test_get_qualification(mocked_get, client):
with override_settings(KNOWN_SERVICES=KNOWN_SERVICES):
forms = mock.Mock()
- forms.json.return_value = {'data': [{'category': 'Test',
- 'authentication_required': False,
- 'description': '',
- 'title': 'Test form',
- 'slug': 'test-form'}],
- 'err': 0}
+ forms.json.return_value = {
+ 'data': [
+ {
+ 'category': 'Test',
+ 'authentication_required': False,
+ 'description': '',
+ 'title': 'Test form',
+ 'slug': 'test-form',
+ }
+ ],
+ 'err': 0,
+ }
mocked_get.return_value = forms
user = mock.Mock()
diff --git a/tests/test_source_maarch.py b/tests/test_source_maarch.py
index 231f1c6..c323122 100644
--- a/tests/test_source_maarch.py
+++ b/tests/test_source_maarch.py
@@ -59,11 +59,13 @@ class MaarchMock(BaseMock):
},
'status_code': 200,
}
+
list_endpoint.path = '^/rest/res/list$'
def update_external_infos(self, url, request):
self.requests.append(('update_external_infos', url, request, json.loads(force_text(request.body))))
return json.dumps({})
+
update_external_infos.path = '^/rest/res/externalInfos$'
def update_status(self, url, request):
@@ -75,10 +77,12 @@ class MaarchMock(BaseMock):
},
'status_code': 200,
}
+
update_status.path = '^/rest/res/resource/status$'
def post_courrier(self, url, request):
self.requests.append(('post_courrier', url, request, json.loads(force_text(request.body))))
+
post_courrier.path = '^/rest/res$'
@@ -96,37 +100,50 @@ def maarch(settings, mail_group):
class WcsMock(BaseMock):
def api_formdefs(self, url, request):
- return json.dumps({
- 'data': [{
- 'slug': 'slug1',
- 'title': 'title1',
- }]
- })
+ return json.dumps(
+ {
+ 'data': [
+ {
+ 'slug': 'slug1',
+ 'title': 'title1',
+ }
+ ]
+ }
+ )
+
api_formdefs.path = '^/api/formdefs/$'
def json(self, url, request):
- return json.dumps({
- 'data': [{
- 'slug': 'slug1',
- 'title': 'title1',
- 'category': 'category1',
- }]
- })
+ return json.dumps(
+ {
+ 'data': [
+ {
+ 'slug': 'slug1',
+ 'title': 'title1',
+ 'category': 'category1',
+ }
+ ]
+ }
+ )
+
json.path = '^/json$'
def api_formdefs_slug1_schema(self, url, request):
- return json.dumps({
- })
+ return json.dumps({})
+
api_formdefs_slug1_schema.path = '^/api/formdefs/slug-1/schema$'
def api_formdefs_slug1_submit(self, url, request):
- return json.dumps({
- 'err': 0,
- 'data': {
- 'id': 1,
- 'backoffice_url': 'http://wcs.example.net/slug-1/1',
- },
- })
+ return json.dumps(
+ {
+ 'err': 0,
+ 'data': {
+ 'id': 1,
+ 'backoffice_url': 'http://wcs.example.net/slug-1/1',
+ },
+ }
+ )
+
api_formdefs_slug1_submit.path = '^/api/formdefs/slug-1/submit$'
@@ -172,14 +189,16 @@ def test_feed(settings, app, maarch, wcs, user):
# feed mails from maarch
with maarch.ctx_manager:
# list request
- maarch.responses.append({
- 'resources': [
- {
- 'res_id': 1,
- 'fileBase64Content': force_text(base64.b64encode(PDF_MOCK)),
- }
- ],
- })
+ maarch.responses.append(
+ {
+ 'resources': [
+ {
+ 'res_id': 1,
+ 'fileBase64Content': force_text(base64.b64encode(PDF_MOCK)),
+ }
+ ],
+ }
+ )
# update status request
maarch.responses.append({})
# last list request
@@ -214,20 +233,26 @@ def test_feed(settings, app, maarch, wcs, user):
maarch.clear()
pk = Mail.objects.get().pk
with wcs.ctx_manager, maarch.ctx_manager:
- source_type = str(ContentType.objects.get_for_model(Mail).pk),
+ source_type = (str(ContentType.objects.get_for_model(Mail).pk),)
source_pk = str(pk)
- response = app.get('/ajax/qualification', params={
- 'source_type': source_type,
- 'source_pk': source_pk,
- })
+ response = app.get(
+ '/ajax/qualification',
+ params={
+ 'source_type': source_type,
+ 'source_pk': source_pk,
+ },
+ )
assert len(response.pyquery('a[data-association-pk]')) == 0
- response = app.post('/ajax/qualification', params={
- 'source_type': source_type,
- 'source_pk': str(pk),
- 'formdef_reference': 'demarches:slug-1',
- })
+ response = app.post(
+ '/ajax/qualification',
+ params={
+ 'source_type': source_type,
+ 'source_pk': str(pk),
+ 'formdef_reference': 'demarches:slug-1',
+ },
+ )
# verify qualification was done
assert len(response.pyquery('a[data-association-pk]')) == 1
@@ -243,7 +268,7 @@ def test_feed(settings, app, maarch, wcs, user):
'external_link': 'http://wcs.example.net/slug-1/1',
'res_id': 1,
}
- ]
+ ],
}
# verify we can answer
@@ -260,24 +285,24 @@ def test_feed(settings, app, maarch, wcs, user):
assert response.json['err'] == 1
# verify error when maarch feed is not configured
settings.MAARCH_FEED['ENABLE'] = False
- response = app.post_json('/api/mail/response/',
- params={'mail_id': 'maarch-1', 'content': 'coucou'},
- status=200)
+ response = app.post_json(
+ '/api/mail/response/', params={'mail_id': 'maarch-1', 'content': 'coucou'}, status=200
+ )
assert response.json['err'] == 1
assert response.json['err_desc'] == 'maarch is unconfigured'
settings.MAARCH_FEED['ENABLE'] = True
# verify error when mail_id is unknown
- response = app.post_json('/api/mail/response/',
- params={'mail_id': 'maarch-231', 'content': 'coucou'},
- status=404)
+ response = app.post_json(
+ '/api/mail/response/', params={'mail_id': 'maarch-231', 'content': 'coucou'}, status=404
+ )
assert response.json['err'] == 1
# successfull call
maarch.responses.append({})
with maarch.ctx_manager:
- response = app.post_json('/api/mail/response/',
- params={'mail_id': 'maarch-1', 'content': 'coucou'},
- status=200)
+ response = app.post_json(
+ '/api/mail/response/', params={'mail_id': 'maarch-1', 'content': 'coucou'}, status=200
+ )
assert maarch.requests[0][3] == {
'historyMessage': 'coucou',
'resId': [1],
diff --git a/tests/test_source_phone.py b/tests/test_source_phone.py
index 954c797..4f9415d 100644
--- a/tests/test_source_phone.py
+++ b/tests/test_source_phone.py
@@ -38,95 +38,104 @@ def test_call_start_stop(client):
'callee': '102',
'data': {
'user': 'boby.lapointe',
- }
+ },
}
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneCall.objects.count() == 1
- assert models.PhoneCall.objects.filter(
- caller='0033699999999',
- callee='102',
- data=json.dumps(payload['data']), stop__isnull=True).count() == 1
+ assert (
+ models.PhoneCall.objects.filter(
+ caller='0033699999999', callee='102', data=json.dumps(payload['data']), stop__isnull=True
+ ).count()
+ == 1
+ )
# new start event
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneCall.objects.count() == 2
- assert models.PhoneCall.objects.filter(
- caller='0033699999999',
- callee='102',
- data=json.dumps(payload['data']), stop__isnull=True).count() == 1
+ assert (
+ models.PhoneCall.objects.filter(
+ caller='0033699999999', callee='102', data=json.dumps(payload['data']), stop__isnull=True
+ ).count()
+ == 1
+ )
# first call has been closed
- assert models.PhoneCall.objects.filter(
- caller='0033699999999',
- callee='102',
- data=json.dumps(payload['data']), stop__isnull=False).count() == 1
+ assert (
+ models.PhoneCall.objects.filter(
+ caller='0033699999999', callee='102', data=json.dumps(payload['data']), stop__isnull=False
+ ).count()
+ == 1
+ )
payload['event'] = 'stop'
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneCall.objects.count() == 2
- assert models.PhoneCall.objects.filter(
- caller='0033699999999',
- callee='102',
- data=json.dumps(payload['data']), stop__isnull=False).count() == 2
+ assert (
+ models.PhoneCall.objects.filter(
+ caller='0033699999999', callee='102', data=json.dumps(payload['data']), stop__isnull=False
+ ).count()
+ == 2
+ )
# stop is idempotent
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneCall.objects.count() == 2
- assert models.PhoneCall.objects.filter(
- caller='0033699999999',
- callee='102',
- data=json.dumps(payload['data']), stop__isnull=False).count() == 2
+ assert (
+ models.PhoneCall.objects.filter(
+ caller='0033699999999', callee='102', data=json.dumps(payload['data']), stop__isnull=False
+ ).count()
+ == 2
+ )
def test_one_call_per_callee(user, client):
assert models.PhoneCall.objects.count() == 0
payload = {'event': 'start', 'caller': '0033699999999', 'callee': '102'}
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert models.PhoneCall.objects.filter(callee='102', stop__isnull=True).count() == 1 # active
- assert models.PhoneCall.objects.filter(callee='102', stop__isnull=False).count() == 0 # inactive
+ assert models.PhoneCall.objects.filter(callee='102', stop__isnull=False).count() == 0 # inactive
# new caller, same callee: stops the last call, start a new one
payload['caller'] = '00337123456789'
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert models.PhoneCall.objects.count() == 2
- assert models.PhoneCall.objects.filter(
- caller='00337123456789', callee='102', stop__isnull=True).count() == 1
- assert models.PhoneCall.objects.filter(
- caller='0033699999999', callee='102', stop__isnull=False).count() == 1
+ assert (
+ models.PhoneCall.objects.filter(caller='00337123456789', callee='102', stop__isnull=True).count() == 1
+ )
+ assert (
+ models.PhoneCall.objects.filter(caller='0033699999999', callee='102', stop__isnull=False).count() == 1
+ )
with override_settings(PHONE_ONE_CALL_PER_CALLEE=False):
# accept multiple call: start a new one, don't stop anything
payload['caller'] = '00221774261500'
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(
+ reverse('phone-call-event'), json.dumps(payload), content_type='application/json'
+ )
assert response.status_code == 200
assert models.PhoneCall.objects.count() == 3
assert models.PhoneCall.objects.filter(callee='102', stop__isnull=True).count() == 2
assert models.PhoneCall.objects.filter(callee='102', stop__isnull=False).count() == 1
# same caller: stop his last call, add a new one
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(
+ reverse('phone-call-event'), json.dumps(payload), content_type='application/json'
+ )
assert response.status_code == 200
assert models.PhoneCall.objects.count() == 4
assert models.PhoneCall.objects.filter(callee='102', stop__isnull=True).count() == 2
assert models.PhoneCall.objects.filter(callee='102', stop__isnull=False).count() == 2
+
def test_current_calls(user, client):
# create some calls
for number in range(0, 10):
@@ -136,10 +145,11 @@ def test_current_calls(user, client):
'callee': '1%02d' % number,
'data': {
'user': 'boby.lapointe',
- }
+ },
}
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(
+ reverse('phone-call-event'), json.dumps(payload), content_type='application/json'
+ )
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
@@ -199,22 +209,20 @@ def test_take_release_line(user, client):
payload = {
'callee': '102',
}
- response = client.post(reverse('phone-take-line'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-take-line'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneLine.objects.count() == 1
- assert models.PhoneLine.objects.filter(
- users=user, callee='102').count() == 1
- response = client.post(reverse('phone-release-line'), json.dumps(payload),
- content_type='application/json')
+ assert models.PhoneLine.objects.filter(users=user, callee='102').count() == 1
+ response = client.post(
+ reverse('phone-release-line'), json.dumps(payload), content_type='application/json'
+ )
assert response.status_code == 200
assert response['content-type'] == 'application/json'
assert response.json() == {'err': 0}
assert models.PhoneLine.objects.count() == 1
- assert models.PhoneLine.objects.filter(
- users=user, callee='102').count() == 0
+ assert models.PhoneLine.objects.filter(users=user, callee='102').count() == 0
def test_phone_zone(user, client):
@@ -230,15 +238,16 @@ def test_phone_zone(user, client):
assert 'You do not have a phoneline configured' not in force_text(response.content)
assert '<li>102' in force_text(response.content)
assert 'data-callee="102"' in force_text(response.content)
- currents = re.search('<div id="source-mainarea" '
- 'data-current-calls="/api/phone/current-calls/">'
- '(.*?)</div>', force_text(response.content), flags=re.DOTALL)
+ currents = re.search(
+ '<div id="source-mainarea" ' 'data-current-calls="/api/phone/current-calls/">' '(.*?)</div>',
+ force_text(response.content),
+ flags=re.DOTALL,
+ )
assert currents.group(1).strip() == ''
# create a call
payload = {'event': 'start', 'caller': '003369999999', 'callee': '102'}
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
response = client.get(reverse('phone-zone'))
assert response.status_code == 200
@@ -269,8 +278,7 @@ def test_call_expiration(user, client):
assert models.PhoneCall.objects.count() == 0
# create a call
payload = {'event': 'start', 'caller': '003369999999', 'callee': '102'}
- response = client.post(reverse('phone-call-event'), json.dumps(payload),
- content_type='application/json')
+ response = client.post(reverse('phone-call-event'), json.dumps(payload), content_type='application/json')
assert response.status_code == 200
assert models.PhoneCall.objects.filter(stop__isnull=True).count() == 1
@@ -284,15 +292,14 @@ def test_call_expiration(user, client):
assert len(payload['data']['calls']) == 1
# start call 10 minutes ago
- models.PhoneCall.objects.filter(stop__isnull=True).update(
- start=now()-timedelta(minutes=10))
+ models.PhoneCall.objects.filter(stop__isnull=True).update(start=now() - timedelta(minutes=10))
# get list of calls without expiration
response = client.get(reverse('phone-current-calls'))
assert response.status_code == 200
payload = response.json()
assert payload['err'] == 0
- assert len(payload['data']['calls']) == 1 # still here
+ assert len(payload['data']['calls']) == 1 # still here
# get list of calls with an expiration of 2 minutes (< 10 minutes)
with override_settings(PHONE_MAX_CALL_DURATION=2):
@@ -300,7 +307,7 @@ def test_call_expiration(user, client):
assert response.status_code == 200
payload = response.json()
assert payload['err'] == 0
- assert len(payload['data']['calls']) == 0 # call is expired
+ assert len(payload['data']['calls']) == 0 # call is expired
assert models.PhoneCall.objects.filter(stop__isnull=True).count() == 0 # active calls
- assert models.PhoneCall.objects.filter(stop__isnull=False).count() == 1 # stopped calls
+ assert models.PhoneCall.objects.filter(stop__isnull=False).count() == 1 # stopped calls
diff --git a/welco/apps.py b/welco/apps.py
index d6b79b3..6a6c832 100644
--- a/welco/apps.py
+++ b/welco/apps.py
@@ -17,6 +17,7 @@
from django.apps import apps
from django.conf.urls import include, url
+
def register_urls(urlpatterns):
pre_urls = []
post_urls = []
diff --git a/welco/contacts/forms.py b/welco/contacts/forms.py
index a903201..e9d890a 100644
--- a/welco/contacts/forms.py
+++ b/welco/contacts/forms.py
@@ -24,14 +24,15 @@ DEFAULT_TITLE_CHOICES = (
(pgettext_lazy('title', 'Mr'), pgettext_lazy('title', 'Mr')),
)
+
class ContactAddForm(forms.Form):
- title = forms.CharField(label=_('Title'),
- required=False,
- widget=forms.Select(choices=DEFAULT_TITLE_CHOICES))
+ title = forms.CharField(
+ label=_('Title'), required=False, widget=forms.Select(choices=DEFAULT_TITLE_CHOICES)
+ )
first_name = forms.CharField(label=_('First Name'), required=False)
- last_name = forms.CharField(label=_('Last Name'),
- required=True,
- widget=forms.TextInput(attrs={'required': 'required'}))
+ last_name = forms.CharField(
+ label=_('Last Name'), required=True, widget=forms.TextInput(attrs={'required': 'required'})
+ )
email = forms.CharField(label=_('Email'), required=False)
address = forms.CharField(label=_('Address'), required=False)
zipcode = forms.CharField(label=_('Zip Code'), required=False)
diff --git a/welco/contacts/views.py b/welco/contacts/views.py
index 956ae19..331195b 100644
--- a/welco/contacts/views.py
+++ b/welco/contacts/views.py
@@ -33,6 +33,7 @@ from welco.utils import get_wcs_data, sign_url
from .forms import ContactAddForm
+
class HomeZone(object):
def __init__(self, request):
self.request = request
@@ -49,21 +50,20 @@ class ContactsZone(TemplateView):
context = super(ContactsZone, self).get_context_data(**kwargs)
context['source_pk'] = self.request.GET.get('source_pk')
if 'source_pk' in self.request.GET:
- source_class = ContentType.objects.get(
- id=self.request.GET['source_type']).model_class()
+ source_class = ContentType.objects.get(id=self.request.GET['source_type']).model_class()
source_object = source_class.objects.get(id=self.request.GET['source_pk'])
context['contact_user_id'] = source_object.contact_id
return context
def post(self, request, *args, **kwargs):
if 'user_id' in request.POST:
- source_class = ContentType.objects.get(
- id=self.request.POST['source_type']).model_class()
+ source_class = ContentType.objects.get(id=self.request.POST['source_type']).model_class()
source_object = source_class.objects.get(id=self.request.POST['source_pk'])
source_object.contact_id = request.POST['user_id']
source_object.save()
return HttpResponse('ok')
+
zone = csrf_exempt(ContactsZone.as_view())
@@ -83,8 +83,12 @@ def search_json(request):
raise Exception('error %r' % result)
for user in result.get('data'):
user['title'] = user['user_display_name']
- more = [user.get('user_var_address'), user.get('user_var_phone'),
- user.get('user_var_mobile'), user.get('user_var_email')]
+ more = [
+ user.get('user_var_address'),
+ user.get('user_var_phone'),
+ user.get('user_var_mobile'),
+ user.get('user_var_email'),
+ ]
user['more'] = ' / '.join([x for x in more if x])
if user.get('user_roles'):
user['roles'] = ' / '.join([r['text'] for r in user['user_roles']])
@@ -109,13 +113,13 @@ class ContactDetailFragmentView(TemplateView):
context['user_id'] = user_id
if 'source_pk' in self.request.GET:
- source_class = ContentType.objects.get(
- id=self.request.GET['source_type']).model_class()
+ source_class = ContentType.objects.get(id=self.request.GET['source_type']).model_class()
source_object = source_class.objects.get(id=self.request.GET['source_pk'])
context['is_pinned_user'] = bool(source_object.contact_id == user_id)
return context
+
contact_detail_fragment = ContactDetailFragmentView.as_view()
@@ -144,9 +148,8 @@ class ContactAdd(FormView):
logger = logging.getLogger(__name__)
logger.info('POST to authentic (%r)', json.dumps(msg))
authentic_response = requests.post(
- signed_url,
- data=json.dumps(msg),
- headers={'Content-type': 'application/json'})
+ signed_url, data=json.dumps(msg), headers={'Content-type': 'application/json'}
+ )
logger.info('Got authentic response (%r)', authentic_response.text)
user_uuid = authentic_response.json().get('uuid')
@@ -165,4 +168,5 @@ class ContactAdd(FormView):
json.dump(result, response, indent=2)
return response
+
contact_add = csrf_exempt(ContactAdd.as_view())
diff --git a/welco/kb/apps.py b/welco/kb/apps.py
index 4aebdc0..e19126d 100644
--- a/welco/kb/apps.py
+++ b/welco/kb/apps.py
@@ -16,6 +16,7 @@
from django.apps import AppConfig
+
class KbAppConfig(AppConfig):
name = 'welco.kb'
diff --git a/welco/kb/forms.py b/welco/kb/forms.py
index e185821..9e0feef 100644
--- a/welco/kb/forms.py
+++ b/welco/kb/forms.py
@@ -19,6 +19,7 @@ from django.utils.text import slugify
from .models import Page
+
class PageForm(forms.ModelForm):
class Meta:
model = Page
diff --git a/welco/kb/migrations/0001_initial.py b/welco/kb/migrations/0001_initial.py
index 05b359c..10fdb7b 100644
--- a/welco/kb/migrations/0001_initial.py
+++ b/welco/kb/migrations/0001_initial.py
@@ -7,14 +7,16 @@ import ckeditor.fields
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
name='Page',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('title', models.CharField(max_length=200, verbose_name='Title')),
('slug', models.SlugField(verbose_name='Slug')),
('content', ckeditor.fields.RichTextField(verbose_name='Text')),
diff --git a/welco/kb/migrations/0003_page_tags.py b/welco/kb/migrations/0003_page_tags.py
index d91559d..0f76b13 100644
--- a/welco/kb/migrations/0003_page_tags.py
+++ b/welco/kb/migrations/0003_page_tags.py
@@ -16,7 +16,13 @@ class Migration(migrations.Migration):
migrations.AddField(
model_name='page',
name='tags',
- field=taggit.managers.TaggableManager(to='taggit.Tag', through='taggit.TaggedItem', blank=True, help_text='A comma-separated list of tags.', verbose_name='Keywords'),
+ field=taggit.managers.TaggableManager(
+ to='taggit.Tag',
+ through='taggit.TaggedItem',
+ blank=True,
+ help_text='A comma-separated list of tags.',
+ verbose_name='Keywords',
+ ),
preserve_default=True,
),
]
diff --git a/welco/kb/models.py b/welco/kb/models.py
index 1e3b817..7c40dfa 100644
--- a/welco/kb/models.py
+++ b/welco/kb/models.py
@@ -26,8 +26,7 @@ class Page(models.Model):
title = models.CharField(_('Title'), max_length=200)
slug = models.SlugField(_('Slug'))
content = RichTextField(_('Text'))
- tags = TaggableManager(_('Keywords'), blank=True,
- help_text=_('A comma-separated list of tags.'))
+ tags = TaggableManager(_('Keywords'), blank=True, help_text=_('A comma-separated list of tags.'))
class Meta:
ordering = ['title']
diff --git a/welco/kb/search_indexes.py b/welco/kb/search_indexes.py
index f4f388b..ec24f70 100644
--- a/welco/kb/search_indexes.py
+++ b/welco/kb/search_indexes.py
@@ -21,6 +21,7 @@ from haystack import indexes
from .models import Page
+
class PageIndex(indexes.SearchIndex, indexes.Indexable):
title = indexes.CharField(model_attr='title', boost=3)
text = indexes.CharField(document=True)
diff --git a/welco/kb/views.py b/welco/kb/views.py
index b2010d2..64366c4 100644
--- a/welco/kb/views.py
+++ b/welco/kb/views.py
@@ -25,8 +25,7 @@ from django.db.models import Count
from django.http import HttpResponse, HttpResponseRedirect
from django.template import RequestContext
from django.views.decorators.csrf import csrf_exempt
-from django.views.generic import (DetailView, CreateView, UpdateView,
- ListView, DeleteView, TemplateView)
+from django.views.generic import DetailView, CreateView, UpdateView, ListView, DeleteView, TemplateView
from haystack.forms import SearchForm
from haystack.generic_views import SearchView
@@ -36,15 +35,17 @@ from taggit.models import Tag
from .models import Page
from .forms import PageForm
+
def check_user_perms(user, access=False):
allowed_roles = settings.KB_MANAGE_ROLES[:]
if access:
allowed_roles.extend(settings.KB_ACCESS_ROLES)
if settings.KB_ROLE:
- allowed_roles.append(settings.KB_ROLE) # legacy
+ allowed_roles.append(settings.KB_ROLE) # legacy
user_groups = set([x.name for x in user.groups.all()])
return user_groups.intersection(allowed_roles)
+
def check_request_perms(request, access=False):
if not check_user_perms(request.user, access=access):
raise PermissionDenied()
@@ -63,6 +64,7 @@ class PageListView(ListView):
context['can_manage'] = check_user_perms(self.request.user)
return context
+
page_list = login_required(PageListView.as_view())
@@ -74,6 +76,7 @@ class PageAddView(CreateView):
check_request_perms(request)
return super(PageAddView, self).dispatch(request, *args, **kwargs)
+
page_add = login_required(PageAddView.as_view())
@@ -85,6 +88,7 @@ class PageEditView(UpdateView):
check_request_perms(request)
return super(PageEditView, self).dispatch(request, *args, **kwargs)
+
page_edit = login_required(PageEditView.as_view())
@@ -108,6 +112,7 @@ class PageDetailFragmentView(DetailView):
model = Page
template_name = 'kb/page_detail_fragment.html'
+
page_detail_fragment = PageDetailFragmentView.as_view()
@@ -119,6 +124,7 @@ class PageDeleteView(DeleteView):
check_request_perms(request)
return super(PageDeleteView, self).dispatch(request, *args, **kwargs)
+
page_delete = login_required(PageDeleteView.as_view())
@@ -130,6 +136,7 @@ class PageSearchView(SearchView):
check_request_perms(request, access=True)
return super(PageSearchView, self).dispatch(request, *args, **kwargs)
+
page_search = login_required(PageSearchView.as_view())
@@ -140,8 +147,9 @@ class KbZone(TemplateView):
context = super(KbZone, self).get_context_data(**kwargs)
context['source_pk'] = self.request.GET.get('source_pk')
context['form'] = SearchForm()
- context['tags'] = Tag.objects.all().annotate(
- num_times=Count('taggit_taggeditem_items')).filter(num_times__gt=0)
+ context['tags'] = (
+ Tag.objects.all().annotate(num_times=Count('taggit_taggeditem_items')).filter(num_times__gt=0)
+ )
num_times = context['tags'].values_list('num_times', flat=True)
if not num_times:
num_times = [0]
@@ -163,6 +171,7 @@ class KbZone(TemplateView):
tag.font_size = 'x-large'
return context
+
zone = csrf_exempt(KbZone.as_view())
diff --git a/welco/monkeypatch.py b/welco/monkeypatch.py
index bf80fa0..63116a0 100644
--- a/welco/monkeypatch.py
+++ b/welco/monkeypatch.py
@@ -24,6 +24,7 @@ from django.utils.translation import get_language
import ckeditor.widgets
+
def ckeditor_render(self, name, value, attrs=None):
if value is None:
value = ''
@@ -40,14 +41,22 @@ def ckeditor_render(self, name, value, attrs=None):
self.config['language'] = get_language()
# Force to text to evaluate possible lazy objects
- external_plugin_resources = [[force_text(a), force_text(b), force_text(c)] for a, b, c in self.external_plugin_resources]
-
- return mark_safe(render_to_string('ckeditor/widget.html', {
- 'final_attrs': flatatt(final_attrs),
- 'value': conditional_escape(force_text(value)),
- 'id': final_attrs['id'],
- 'config': ckeditor.widgets.json_encode(self.config),
- 'external_plugin_resources' : ckeditor.widgets.json_encode(external_plugin_resources)
- }))
+ external_plugin_resources = [
+ [force_text(a), force_text(b), force_text(c)] for a, b, c in self.external_plugin_resources
+ ]
+
+ return mark_safe(
+ render_to_string(
+ 'ckeditor/widget.html',
+ {
+ 'final_attrs': flatatt(final_attrs),
+ 'value': conditional_escape(force_text(value)),
+ 'id': final_attrs['id'],
+ 'config': ckeditor.widgets.json_encode(self.config),
+ 'external_plugin_resources': ckeditor.widgets.json_encode(external_plugin_resources),
+ },
+ )
+ )
+
ckeditor.widgets.CKEditorWidget.render = ckeditor_render
diff --git a/welco/qualif/migrations/0001_initial.py b/welco/qualif/migrations/0001_initial.py
index 0606fdd..61c9943 100644
--- a/welco/qualif/migrations/0001_initial.py
+++ b/welco/qualif/migrations/0001_initial.py
@@ -14,31 +14,37 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='Association',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('source_pk', models.PositiveIntegerField()),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='FormdataReference',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('reference', models.CharField(max_length=250)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.CreateModel(
name='FormdefReference',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('reference', models.CharField(max_length=250)),
],
- options={
- },
+ options={},
bases=(models.Model,),
),
migrations.AddField(
diff --git a/welco/qualif/models.py b/welco/qualif/models.py
index 8f092ad..6eaa6b5 100644
--- a/welco/qualif/models.py
+++ b/welco/qualif/models.py
@@ -38,10 +38,12 @@ class Association(models.Model):
if self.source.contact_id:
context['user_id'] = self.source.contact_id
context['summary_url'] = request.build_absolute_uri(
- reverse('wcs-summary', kwargs={'source_type': self.source_type_id,
- 'source_pk': self.source_pk}))
+ reverse('wcs-summary', kwargs={'source_type': self.source_type_id, 'source_pk': self.source_pk})
+ )
context.update(self.source.get_source_context(request))
- self.formdata_id, self.formdata_url_backoffice = push_wcs_formdata(request, self.formdef_reference, context)
+ self.formdata_id, self.formdata_url_backoffice = push_wcs_formdata(
+ request, self.formdef_reference, context
+ )
self.save()
@property
diff --git a/welco/settings.py b/welco/settings.py
index 03f93d1..9bc97ff 100644
--- a/welco/settings.py
+++ b/welco/settings.py
@@ -90,7 +90,7 @@ USE_L10N = True
USE_TZ = True
-LOCALE_PATHS = (os.path.join(BASE_DIR, 'welco', 'locale'), )
+LOCALE_PATHS = (os.path.join(BASE_DIR, 'welco', 'locale'),)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/
@@ -99,9 +99,7 @@ STATIC_URL = '/static/'
STATICFILES_FINDERS = tuple(global_settings.STATICFILES_FINDERS) + ('gadjo.finders.XStaticFinder',)
-STATICFILES_DIRS = (
- os.path.join(BASE_DIR, 'welco', 'static'),
-)
+STATICFILES_DIRS = (os.path.join(BASE_DIR, 'welco', 'static'),)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
@@ -131,12 +129,18 @@ CKEDITOR_UPLOAD_PATH = 'uploads/'
CKEDITOR_CONFIGS = {
'default': {
- 'toolbar_Own': [['Source', 'Format', '-', 'Bold', 'Italic'],
- ['NumberedList', 'BulletedList'],
- ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
- ['Link', 'Unlink'],
- ['Image',],
- ['RemoveFormat',]],
+ 'toolbar_Own': [
+ ['Source', 'Format', '-', 'Bold', 'Italic'],
+ ['NumberedList', 'BulletedList'],
+ ['JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock'],
+ ['Link', 'Unlink'],
+ [
+ 'Image',
+ ],
+ [
+ 'RemoveFormat',
+ ],
+ ],
'toolbar': 'Own',
},
}
@@ -190,7 +194,7 @@ CHANNEL_ROLES = {
}
# role allowed to manage knowledge base
-KB_ROLE = None # deprecated
+KB_ROLE = None # deprecated
KB_MANAGE_ROLES = []
# roles allowed to visit knowledge base
@@ -200,9 +204,7 @@ KB_ACCESS_ROLES = []
SCREEN_PANELS = ['contacts', 'qualif']
# useful links for counter
-COUNTER_LINKS = [
- {'label': 'Wikipedia', 'url': 'https://fr.wikipedia.org'}
-]
+COUNTER_LINKS = [{'label': 'Wikipedia', 'url': 'https://fr.wikipedia.org'}]
# phone system
PHONE_ONE_CALL_PER_CALLEE = True
@@ -214,7 +216,8 @@ PHONE_AUTOTAKE_MELLON_USERNAME = False
REST_FRAMEWORK = {}
REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] = ['rest_framework.authentication.BasicAuthentication']
-local_settings_file = os.environ.get('WELCO_SETTINGS_FILE',
- os.path.join(os.path.dirname(__file__), 'local_settings.py'))
+local_settings_file = os.environ.get(
+ 'WELCO_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')
+)
if os.path.exists(local_settings_file):
exec(open(local_settings_file).read())
diff --git a/welco/sources/counter/migrations/0001_initial.py b/welco/sources/counter/migrations/0001_initial.py
index 286755e..d154133 100644
--- a/welco/sources/counter/migrations/0001_initial.py
+++ b/welco/sources/counter/migrations/0001_initial.py
@@ -6,14 +6,16 @@ from django.db import models, migrations
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
name='CounterPresence',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('status', models.CharField(max_length=50, verbose_name='Status', blank=True)),
('contact_id', models.CharField(max_length=50, null=True)),
('creation_timestamp', models.DateTimeField(auto_now_add=True)),
diff --git a/welco/sources/counter/models.py b/welco/sources/counter/models.py
index 10b956c..5048d1e 100644
--- a/welco/sources/counter/models.py
+++ b/welco/sources/counter/models.py
@@ -20,16 +20,15 @@ from django.utils.translation import ugettext_lazy as _
from welco.qualif.models import Association
-class CounterPresence(models.Model):
+class CounterPresence(models.Model):
class Meta:
verbose_name = _('Counter Presence')
# common to all source types:
status = models.CharField(_('Status'), blank=True, max_length=50)
contact_id = models.CharField(max_length=50, null=True)
- associations = GenericRelation(Association,
- content_type_field='source_type', object_id_field='source_pk')
+ associations = GenericRelation(Association, content_type_field='source_type', object_id_field='source_pk')
creation_timestamp = models.DateTimeField(auto_now_add=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
diff --git a/welco/sources/counter/views.py b/welco/sources/counter/views.py
index 040ea3d..6138f90 100644
--- a/welco/sources/counter/views.py
+++ b/welco/sources/counter/views.py
@@ -54,6 +54,7 @@ class CounterZone(TemplateView):
context['useful_links'] = settings.COUNTER_LINKS
return context
+
zone = csrf_exempt(CounterZone.as_view())
diff --git a/welco/sources/mail/__init__.py b/welco/sources/mail/__init__.py
index 0304d62..5a86f3f 100644
--- a/welco/sources/mail/__init__.py
+++ b/welco/sources/mail/__init__.py
@@ -22,14 +22,14 @@ class AppConfig(django.apps.AppConfig):
def get_before_urls(self):
from . import urls
+
return urls.urlpatterns
def ready(self):
from welco.qualif.models import Association
from django.db.models import signals
- signals.post_save.connect(self.association_post_save,
- sender=Association)
+ signals.post_save.connect(self.association_post_save, sender=Association)
def association_post_save(self, sender, instance, **kwargs):
from .utils import get_maarch
@@ -47,6 +47,8 @@ class AppConfig(django.apps.AppConfig):
maarch.set_grc_sent_status(
mail_pk=maarch_pk,
formdata_id=instance.formdata_id,
- formdata_url_backoffice=instance.formdata_url_backoffice)
+ formdata_url_backoffice=instance.formdata_url_backoffice,
+ )
+
default_app_config = 'welco.sources.mail.AppConfig'
diff --git a/welco/sources/mail/forms.py b/welco/sources/mail/forms.py
index b49e766..fd4136a 100644
--- a/welco/sources/mail/forms.py
+++ b/welco/sources/mail/forms.py
@@ -18,6 +18,7 @@ from django import forms
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
+
class MailQualificationForm(forms.Form):
post_date = forms.DateTimeField(label=_('Post Date (*)'), required=False)
registered_mail_number = forms.CharField(label=_('Registered Mail Number'), required=False)
diff --git a/welco/sources/mail/maarch.py b/welco/sources/mail/maarch.py
index 11283fa..f84f46a 100644
--- a/welco/sources/mail/maarch.py
+++ b/welco/sources/mail/maarch.py
@@ -125,7 +125,7 @@ class MaarchCourrier(object):
read=self.max_retries,
connect=self.max_retries,
backoff_factor=0.5,
- status_forcelist=(500, 502, 504)
+ status_forcelist=(500, 502, 504),
)
adapter = HTTPAdapter(max_retries=retry)
s.mount('http://', adapter)
@@ -175,13 +175,16 @@ class MaarchCourrier(object):
fields = ','.join(fields) if fields else '*'
limit = limit or self.default_limit
order_by = order_by or []
- response = self.post_json(self.list_url, {
- 'select': fields,
- 'clause': clause,
- 'limit': limit,
- 'withFile': include_file,
- 'orderBy': order_by,
- })
+ response = self.post_json(
+ self.list_url,
+ {
+ 'select': fields,
+ 'clause': clause,
+ 'limit': limit,
+ 'withFile': include_file,
+ 'orderBy': order_by,
+ },
+ )
if not hasattr(response.get('resources'), 'append'):
raise MaarchError('missing resources field or bad type', response)
return [self.Courrier(self, **resource) for resource in response['resources']]
diff --git a/welco/sources/mail/management/commands/feed_mail.py b/welco/sources/mail/management/commands/feed_mail.py
index fc36f2f..baef5ea 100644
--- a/welco/sources/mail/management/commands/feed_mail.py
+++ b/welco/sources/mail/management/commands/feed_mail.py
@@ -22,10 +22,10 @@ from django.core.management.base import BaseCommand, CommandError
from ...models import Mail
+
class Command(BaseCommand):
def add_arguments(self, parser):
- parser.add_argument(
- '--category', metavar='CATEGORY', default=None)
+ parser.add_argument('--category', metavar='CATEGORY', default=None)
parser.add_argument('filenames', metavar='FILENAME', nargs='+')
def handle(self, filenames, *args, **kwargs):
diff --git a/welco/sources/mail/management/commands/feed_mail_maarch.py b/welco/sources/mail/management/commands/feed_mail_maarch.py
index 6166600..88631c3 100644
--- a/welco/sources/mail/management/commands/feed_mail_maarch.py
+++ b/welco/sources/mail/management/commands/feed_mail_maarch.py
@@ -25,14 +25,15 @@ from django.db import transaction
from ...models import Mail
from ...utils import get_maarch
+
class Command(BaseCommand):
"""Inject mail coming from Maarch into welco.
- Only mail with a status "GRC" are injected,
- After injection, their status is immediately changed to "GRC_TRT".
- After injection in w.c.s., their status is changed to "GRCSENT" and an
- id and an URL of the request in w.c.s. is attached to the mail in
- Maarch.
+ Only mail with a status "GRC" are injected,
+ After injection, their status is immediately changed to "GRC_TRT".
+ After injection in w.c.s., their status is changed to "GRCSENT" and an
+ id and an URL of the request in w.c.s. is attached to the mail in
+ Maarch.
"""
def handle(self, *args, **kwargs):
diff --git a/welco/sources/mail/migrations/0001_initial.py b/welco/sources/mail/migrations/0001_initial.py
index b140b74..b6ef78c 100644
--- a/welco/sources/mail/migrations/0001_initial.py
+++ b/welco/sources/mail/migrations/0001_initial.py
@@ -6,14 +6,16 @@ from django.db import models, migrations
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
name='Mail',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('content', models.FileField(upload_to=b'', verbose_name='Content')),
('triaged', models.BooleanField(default=False)),
('creation_timestamp', models.DateTimeField(auto_now_add=True)),
diff --git a/welco/sources/mail/migrations/0011_mail_reference.py b/welco/sources/mail/migrations/0011_mail_reference.py
index 96347aa..a1af01e 100644
--- a/welco/sources/mail/migrations/0011_mail_reference.py
+++ b/welco/sources/mail/migrations/0011_mail_reference.py
@@ -18,7 +18,6 @@ class Migration(migrations.Migration):
),
migrations.AlterModelOptions(
name='mail',
- options={'ordering': ['post_date', 'creation_timestamp'],
- 'verbose_name': 'Mail'},
+ options={'ordering': ['post_date', 'creation_timestamp'], 'verbose_name': 'Mail'},
),
]
diff --git a/welco/sources/mail/models.py b/welco/sources/mail/models.py
index da62f9c..365847e 100644
--- a/welco/sources/mail/models.py
+++ b/welco/sources/mail/models.py
@@ -32,15 +32,13 @@ from welco.utils import get_wcs_data
class Mail(models.Model):
-
class Meta:
verbose_name = _('Mail')
ordering = ['post_date', 'creation_timestamp']
content = models.FileField(_('Content'))
post_date = models.DateField(_('Post Date'), null=True)
- registered_mail_number = models.CharField(_('Registered Mail Number'),
- null=True, max_length=50)
+ registered_mail_number = models.CharField(_('Registered Mail Number'), null=True, max_length=50)
note = models.TextField(_('Note'), null=True)
external_id = models.CharField(_('External Id'), null=True, max_length=32)
@@ -52,8 +50,7 @@ class Mail(models.Model):
# common to all source types:
status = models.CharField(_('Status'), blank=True, max_length=50)
contact_id = models.CharField(max_length=50, null=True)
- associations = GenericRelation(Association,
- content_type_field='source_type', object_id_field='source_pk')
+ associations = GenericRelation(Association, content_type_field='source_type', object_id_field='source_pk')
creation_timestamp = models.DateTimeField(auto_now_add=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
@@ -61,6 +58,7 @@ class Mail(models.Model):
@classmethod
def get_qualification_form_class(cls):
from .forms import MailQualificationForm
+
return MailQualificationForm
def get_qualification_form(self):
@@ -111,5 +109,13 @@ class Mail(models.Model):
def create_thumbnail(sender, instance, created, **kwargs):
if not created:
return
- subprocess.call(['gm', 'convert', '-geometry', '200x',
- instance.content.file.name, instance.content.file.name + '.png'])
+ subprocess.call(
+ [
+ 'gm',
+ 'convert',
+ '-geometry',
+ '200x',
+ instance.content.file.name,
+ instance.content.file.name + '.png',
+ ]
+ )
diff --git a/welco/sources/mail/urls.py b/welco/sources/mail/urls.py
index 272c250..5df4848 100644
--- a/welco/sources/mail/urls.py
+++ b/welco/sources/mail/urls.py
@@ -16,8 +16,7 @@
from django.conf.urls import url
-from .views import (viewer, feeder, qualification_save, edit_note, note,
- reject, mail_count, mail_response)
+from .views import viewer, feeder, qualification_save, edit_note, note, reject, mail_count, mail_response
urlpatterns = [
url('viewer/$', viewer, name='mail-viewer'),
diff --git a/welco/sources/mail/utils.py b/welco/sources/mail/utils.py
index 953e73a..2d9b1a0 100644
--- a/welco/sources/mail/utils.py
+++ b/welco/sources/mail/utils.py
@@ -20,9 +20,18 @@ from .maarch import MaarchCourrier, MaarchError
class WelcoMaarchCourrier(MaarchCourrier):
- def __init__(self, url, username, password, grc_status,
- grc_received_status, grc_send_status, grc_refused_status,
- grc_response_status, batch_size=10):
+ def __init__(
+ self,
+ url,
+ username,
+ password,
+ grc_status,
+ grc_received_status,
+ grc_send_status,
+ grc_refused_status,
+ grc_response_status,
+ batch_size=10,
+ ):
super(WelcoMaarchCourrier, self).__init__(url, username, password)
self.grc_status = grc_status
self.grc_received_status = grc_received_status
@@ -36,7 +45,8 @@ class WelcoMaarchCourrier(MaarchCourrier):
clause="status='%s'" % self.grc_status,
include_file=True,
order_by=['res_id'],
- limit=self.batch_size)
+ limit=self.batch_size,
+ )
def get_mail(self, mail_id):
return self.get_courriers(clause="res_id=%s" % mail_id)[0]
@@ -74,5 +84,5 @@ def get_maarch():
grc_received_status=config.get('STATUS_RECEIVED', 'GRC_TRT'),
grc_send_status=config.get('STATUS_SEND', 'GRCSENT'),
grc_refused_status=config.get('STATUS_REFUSED', 'GRCREFUSED'),
- grc_response_status=config.get('STATUS_RESPONSE', 'GRC_RESPONSE'))
-
+ grc_response_status=config.get('STATUS_RESPONSE', 'GRC_RESPONSE'),
+ )
diff --git a/welco/sources/mail/views.py b/welco/sources/mail/views.py
index 67e2e2a..64979a3 100644
--- a/welco/sources/mail/views.py
+++ b/welco/sources/mail/views.py
@@ -42,11 +42,11 @@ from .utils import get_maarch, MaarchError
logger = logging.getLogger(__name__)
+
def viewer(request, *args, **kwargs):
if not 'file' in request.GET:
return HttpResponseRedirect('?file=')
- body = template.loader.get_template('welco/mail_viewer.html').render(
- request=request)
+ body = template.loader.get_template('welco/mail_viewer.html').render(request=request)
return HttpResponse(body)
@@ -57,12 +57,13 @@ class Feeder(TemplateView):
for upload in request.FILES.getlist('mail'):
mail = Mail(content=upload)
mail.save()
- messages.info(request, _('%d files uploaded successfully.') %
- len(request.FILES.getlist('mail')))
+ messages.info(request, _('%d files uploaded successfully.') % len(request.FILES.getlist('mail')))
return HttpResponseRedirect(reverse('mail-feeder'))
+
feeder = login_required(csrf_exempt(Feeder.as_view()))
+
class Home(object):
source_key = 'mail'
display_filter = True
@@ -101,9 +102,10 @@ def qualification_save(request, *args, **kwargs):
mail.reference = form.cleaned_data['reference']
mail.subject = form.cleaned_data['subject']
mail.save()
- return HttpResponseRedirect(reverse('qualif-zone') +
- '?source_type=%s&source_pk=%s' % (request.POST['source_type'],
- request.POST['source_pk']))
+ return HttpResponseRedirect(
+ reverse('qualif-zone')
+ + '?source_type=%s&source_pk=%s' % (request.POST['source_type'], request.POST['source_pk'])
+ )
class EditNote(TemplateView):
@@ -120,6 +122,7 @@ class EditNote(TemplateView):
mail.save()
return HttpResponse(json.dumps({'result': 'ok'}))
+
edit_note = login_required(csrf_exempt(EditNote.as_view()))
@@ -192,4 +195,5 @@ class MailResponseAPIView(GenericAPIView):
return Response({'err': 1, 'err_desc': str(e)})
return Response({'err': 0})
+
mail_response = MailResponseAPIView.as_view()
diff --git a/welco/sources/phone/migrations/0001_initial.py b/welco/sources/phone/migrations/0001_initial.py
index c64f164..6072cd7 100644
--- a/welco/sources/phone/migrations/0001_initial.py
+++ b/welco/sources/phone/migrations/0001_initial.py
@@ -6,14 +6,16 @@ from django.db import migrations, models
class Migration(migrations.Migration):
- dependencies = [
- ]
+ dependencies = []
operations = [
migrations.CreateModel(
name='PhoneCall',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('number', models.CharField(max_length=20, verbose_name='Number')),
('creation_timestamp', models.DateTimeField(auto_now_add=True)),
('last_update_timestamp', models.DateTimeField(auto_now=True)),
diff --git a/welco/sources/phone/migrations/0002_auto_20151028_1635.py b/welco/sources/phone/migrations/0002_auto_20151028_1635.py
index 332b4e3..4c1dd3d 100644
--- a/welco/sources/phone/migrations/0002_auto_20151028_1635.py
+++ b/welco/sources/phone/migrations/0002_auto_20151028_1635.py
@@ -19,7 +19,10 @@ class Migration(migrations.Migration):
migrations.CreateModel(
name='PhoneLine',
fields=[
- ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
+ (
+ 'id',
+ models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
+ ),
('callee', models.CharField(unique=True, max_length=20, verbose_name='Callee')),
('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='User')),
],
diff --git a/welco/sources/phone/models.py b/welco/sources/phone/models.py
index 387bc20..7d152cd 100644
--- a/welco/sources/phone/models.py
+++ b/welco/sources/phone/models.py
@@ -25,8 +25,8 @@ from django.utils.timezone import now, timedelta
from welco.qualif.models import Association
-class PhoneCall(models.Model):
+class PhoneCall(models.Model):
class Meta:
verbose_name = _('Phone Call')
@@ -39,8 +39,7 @@ class PhoneCall(models.Model):
# common to all source types:
status = models.CharField(_('Status'), blank=True, max_length=50)
contact_id = models.CharField(max_length=50, null=True)
- associations = GenericRelation(Association,
- content_type_field='source_type', object_id_field='source_pk')
+ associations = GenericRelation(Association, content_type_field='source_type', object_id_field='source_pk')
creation_timestamp = models.DateTimeField(auto_now_add=True)
last_update_timestamp = models.DateTimeField(auto_now=True)
@@ -61,14 +60,13 @@ class PhoneCall(models.Model):
if settings.PHONE_MAX_CALL_DURATION:
logger = logging.getLogger(__name__)
start_after = now() - timedelta(minutes=settings.PHONE_MAX_CALL_DURATION)
- for call in cls.objects.filter(callee__in=PhoneLine.get_callees(user),
- stop__isnull=True,
- start__lt=start_after):
+ for call in cls.objects.filter(
+ callee__in=PhoneLine.get_callees(user), stop__isnull=True, start__lt=start_after
+ ):
logger.info('stop expired call from %s to %s', call.caller, call.callee)
call.stop = now()
call.save()
- return cls.objects.filter(callee__in=PhoneLine.get_callees(user),
- stop__isnull=True).order_by('start')
+ return cls.objects.filter(callee__in=PhoneLine.get_callees(user), stop__isnull=True).order_by('start')
@classmethod
def get_all_callees(cls):
@@ -80,15 +78,15 @@ class PhoneCall(models.Model):
}
def previous_calls(self):
- return PhoneCall.objects.filter(caller=self.caller).exclude(
- id=self.id).order_by('-start')[:5]
+ return PhoneCall.objects.filter(caller=self.caller).exclude(id=self.id).order_by('-start')[:5]
@property
def duration(self):
if not self.stop:
return 'n.a.'
seconds = (self.stop - self.start).seconds
- return '%02d:%02d' % (seconds//60, seconds%60)
+ return '%02d:%02d' % (seconds // 60, seconds % 60)
+
class PhoneLine(models.Model):
callee = models.CharField(_('Callee'), unique=True, max_length=80)
diff --git a/welco/sources/phone/views.py b/welco/sources/phone/views.py
index 9093273..dc50404 100644
--- a/welco/sources/phone/views.py
+++ b/welco/sources/phone/views.py
@@ -57,7 +57,7 @@ class PhoneZone(TemplateView):
username = self.request.session.get('mellon_session', {}).get('username')
if username:
# user is from SSO, username is a phone line (callee), create a link to it
- username = username[0].split('@', 1)[0][:80] # remove realm
+ username = username[0].split('@', 1)[0][:80] # remove realm
if username:
PhoneLine.take(callee=username, user=self.request.user)
context = super(PhoneZone, self).get_context_data(**kwargs)
@@ -66,50 +66,51 @@ class PhoneZone(TemplateView):
context['phonecalls'] = PhoneCall.get_current_calls(self.request.user)
return context
-zone = csrf_exempt(PhoneZone.as_view())
+zone = csrf_exempt(PhoneZone.as_view())
@csrf_exempt
def call_event(request):
- '''Log a new call start or stop, input is JSON:
-
- {
- 'event': 'start' or 'stop',
- 'caller': '003399999999',
- 'callee': '102',
- 'data': {
- 'user': 'zozo',
- },
- }
- '''
+ """Log a new call start or stop, input is JSON:
+
+ {
+ 'event': 'start' or 'stop',
+ 'caller': '003399999999',
+ 'callee': '102',
+ 'data': {
+ 'user': 'zozo',
+ },
+ }
+ """
logger = logging.getLogger(__name__)
try:
payload = json.loads(force_text(request.body))
assert isinstance(payload, dict), 'payload is not a JSON object'
- assert set(payload.keys()) <= set(['event', 'caller', 'callee', 'data']), \
- 'payload keys must be "event", "caller", "callee" and optionnaly "data"'
- assert set(['event', 'caller', 'callee']) <= set(payload.keys()), \
- 'payload keys must be "event", "caller", "callee" and optionnaly "data"'
+ assert set(payload.keys()) <= set(
+ ['event', 'caller', 'callee', 'data']
+ ), 'payload keys must be "event", "caller", "callee" and optionnaly "data"'
+ assert set(['event', 'caller', 'callee']) <= set(
+ payload.keys()
+ ), 'payload keys must be "event", "caller", "callee" and optionnaly "data"'
assert payload['event'] in ('start', 'stop'), 'event must be "start" or "stop"'
assert isinstance(payload['caller'], six.string_types), 'caller must be a string'
assert isinstance(payload['callee'], six.string_types), 'callee must be a string'
if 'data' in payload:
assert isinstance(payload['data'], dict), 'data must be a JSON object'
except (TypeError, ValueError, AssertionError) as e:
- return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
- force_text(e)}),
- content_type='application/json')
+ return HttpResponseBadRequest(
+ json.dumps({'err': 1, 'msg': force_text(e)}), content_type='application/json'
+ )
# janitoring: stop active calls to the callee
if settings.PHONE_ONE_CALL_PER_CALLEE:
logger.info('stop all calls to %s', payload['callee'])
- PhoneCall.objects.filter(callee=payload['callee'],
- stop__isnull=True).update(stop=now())
+ PhoneCall.objects.filter(callee=payload['callee'], stop__isnull=True).update(stop=now())
else:
logger.info('stop call from %s to %s', payload['caller'], payload['callee'])
- PhoneCall.objects.filter(caller=payload['caller'],
- callee=payload['callee'],
- stop__isnull=True).update(stop=now())
+ PhoneCall.objects.filter(
+ caller=payload['caller'], callee=payload['callee'], stop__isnull=True
+ ).update(stop=now())
if payload['event'] == 'start':
# start a new call
kwargs = {
@@ -129,40 +130,39 @@ def active_call(request, *args, **kwargs):
result = {
'caller': call.caller,
'callee': call.callee,
- 'active': not(bool(call.stop)),
+ 'active': not (bool(call.stop)),
'start_timestamp': call.start.strftime('%Y-%m-%dT%H:%M:%S'),
- }
- return HttpResponse(json.dumps(result, indent=2),
- content_type='application/json')
+ }
+ return HttpResponse(json.dumps(result, indent=2), content_type='application/json')
@login_required
def current_calls(request):
- '''Returns the list of current calls for current user as JSON:
-
- {
- 'err': 0,
- 'data': {
- 'calls': [
- {
- 'caller': '00334545445',
- 'callee': '102',
- 'data': { ... },
- },
- ...
- ],
- 'lines': [
- '102',
- ],
- 'all-lines': [
- '102',
- ],
- }
- }
-
- lines are number the user is currently watching, all-lines is all
- registered numbers.
- '''
+ """Returns the list of current calls for current user as JSON:
+
+ {
+ 'err': 0,
+ 'data': {
+ 'calls': [
+ {
+ 'caller': '00334545445',
+ 'callee': '102',
+ 'data': { ... },
+ },
+ ...
+ ],
+ 'lines': [
+ '102',
+ ],
+ 'all-lines': [
+ '102',
+ ],
+ }
+ }
+
+ lines are number the user is currently watching, all-lines is all
+ registered numbers.
+ """
all_callees = PhoneCall.get_all_callees()
callees = PhoneLine.get_callees(request.user)
phonecalls = PhoneCall.get_current_calls(request.user)
@@ -177,11 +177,13 @@ def current_calls(request):
},
}
for call in phonecalls:
- calls.append({
- 'caller': call.caller,
- 'callee': call.callee,
- 'start': call.start.isoformat('T').split('.')[0],
- })
+ calls.append(
+ {
+ 'caller': call.caller,
+ 'callee': call.callee,
+ 'start': call.start.isoformat('T').split('.')[0],
+ }
+ )
if call.data:
calls[-1]['data'] = json.loads(call.data)
response = HttpResponse(content_type='application/json')
@@ -192,19 +194,19 @@ def current_calls(request):
@csrf_exempt
@login_required
def take_line(request):
- '''Take a line, input is JSON:
+ """Take a line, input is JSON:
- { 'callee': '003369999999' }
- '''
+ { 'callee': '003369999999' }
+ """
logger = logging.getLogger(__name__)
try:
payload = json.loads(force_text(request.body))
assert isinstance(payload, dict), 'payload is not a JSON object'
assert list(payload.keys()) == ['callee'], 'payload must have only one key: callee'
except (TypeError, ValueError, AssertionError) as e:
- return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
- force_text(e)}),
- content_type='application/json')
+ return HttpResponseBadRequest(
+ json.dumps({'err': 1, 'msg': force_text(e)}), content_type='application/json'
+ )
PhoneLine.take(payload['callee'], request.user)
logger.info(u'user %s took line %s', request.user, payload['callee'])
return HttpResponse(json.dumps({'err': 0}), content_type='application/json')
@@ -213,19 +215,19 @@ def take_line(request):
@csrf_exempt
@login_required
def release_line(request):
- '''Release a line, input is JSON:
+ """Release a line, input is JSON:
- { 'callee': '003369999999' }
- '''
+ { 'callee': '003369999999' }
+ """
logger = logging.getLogger(__name__)
try:
payload = json.loads(force_text(request.body))
assert isinstance(payload, dict), 'payload is not a JSON object'
assert list(payload.keys()) == ['callee'], 'payload must have only one key: callee'
except (TypeError, ValueError, AssertionError) as e:
- return HttpResponseBadRequest(json.dumps({'err': 1, 'msg':
- force_text(e)}),
- content_type='application/json')
+ return HttpResponseBadRequest(
+ json.dumps({'err': 1, 'msg': force_text(e)}), content_type='application/json'
+ )
PhoneLine.release(payload['callee'], request.user)
logger.info(u'user %s released line %s', request.user, payload['callee'])
return HttpResponse(json.dumps({'err': 0}), content_type='application/json')
diff --git a/welco/urls.py b/welco/urls.py
index 0ea3085..fc9fc5b 100644
--- a/welco/urls.py
+++ b/welco/urls.py
@@ -39,11 +39,12 @@ urlpatterns = [
url(r'^', include('welco.sources.phone.urls')),
url(r'^', include('welco.sources.counter.urls')),
url(r'^ajax/qualification$', welco.views.qualification, name='qualif-zone'),
- url(r'^ajax/remove-association/(?P<pk>\w+)$',
- welco.views.remove_association, name='ajax-remove-association'),
- url(r'^ajax/create-formdata/(?P<pk>\w+)$',
- welco.views.create_formdata, name='ajax-create-formdata'),
-
+ url(
+ r'^ajax/remove-association/(?P<pk>\w+)$',
+ welco.views.remove_association,
+ name='ajax-remove-association',
+ ),
+ url(r'^ajax/create-formdata/(?P<pk>\w+)$', welco.views.create_formdata, name='ajax-create-formdata'),
url(r'^ajax/kb$', welco.kb.views.zone, name='kb-zone'),
url(r'^kb/$', welco.kb.views.page_list, name='kb-home'),
url(r'^kb/add/$', welco.kb.views.page_add, name='kb-page-add'),
@@ -53,23 +54,27 @@ urlpatterns = [
url(r'^ajax/kb/(?P<slug>[\w-]+)/$', welco.kb.views.page_detail_fragment, name='kb-page-fragment'),
url(r'^kb/(?P<slug>[\w-]+)/edit$', welco.kb.views.page_edit, name='kb-page-edit'),
url(r'^kb/(?P<slug>[\w-]+)/delete$', welco.kb.views.page_delete, name='kb-page-delete'),
-
url(r'^ajax/contacts$', welco.contacts.views.zone, name='contacts-zone'),
url(r'^contacts/search/json/$', welco.contacts.views.search_json, name='contacts-search-json'),
- url(r'^ajax/contacts/(?P<slug>[\w-]+)/$',
- welco.contacts.views.contact_detail_fragment, name='contact-page-fragment'),
+ url(
+ r'^ajax/contacts/(?P<slug>[\w-]+)/$',
+ welco.contacts.views.contact_detail_fragment,
+ name='contact-page-fragment',
+ ),
url(r'^contacts/add/$', welco.contacts.views.contact_add, name='contacts-add'),
-
- url(r'^ajax/summary/(?P<source_type>\w+)/(?P<source_pk>\w+)/$',
- welco.views.wcs_summary, name='wcs-summary'),
-
+ url(
+ r'^ajax/summary/(?P<source_type>\w+)/(?P<source_pk>\w+)/$',
+ welco.views.wcs_summary,
+ name='wcs-summary',
+ ),
url(r'^admin/', admin.site.urls),
url(r'^logout/$', welco.views.logout, name='auth_logout'),
url(r'^login/$', welco.views.login, name='auth_login'),
url(r'^menu.json$', welco.views.menu_json, name='menu_json'),
-
url(r'^ckeditor/upload/', kb_manager_required(ckeditor_views.upload), name='ckeditor_upload'),
- url(r'^ckeditor/browse/', never_cache(kb_manager_required(ckeditor_views.browse)), name='ckeditor_browse'),
+ url(
+ r'^ckeditor/browse/', never_cache(kb_manager_required(ckeditor_views.browse)), name='ckeditor_browse'
+ ),
]
if 'mellon' in settings.INSTALLED_APPS:
diff --git a/welco/utils.py b/welco/utils.py
index ada12d9..b179003 100644
--- a/welco/utils.py
+++ b/welco/utils.py
@@ -36,6 +36,7 @@ def sign_url(url, key, algo='sha256', timestamp=None, nonce=None):
new_query = sign_query(parsed.query, key, algo, timestamp, nonce)
return urlparse.urlunparse(parsed[:4] + (new_query,) + parsed[5:])
+
def sign_query(query, key, algo='sha256', timestamp=None, nonce=None):
if timestamp is None:
timestamp = datetime.datetime.utcnow()
@@ -45,22 +46,22 @@ def sign_query(query, key, algo='sha256', timestamp=None, nonce=None):
new_query = query
if new_query:
new_query += '&'
- new_query += urlencode((
- ('algo', algo),
- ('timestamp', timestamp),
- ('nonce', nonce)))
+ new_query += urlencode((('algo', algo), ('timestamp', timestamp), ('nonce', nonce)))
signature = base64.b64encode(sign_string(new_query, key, algo=algo))
new_query += '&signature=' + quote(signature)
return new_query
+
def sign_string(s, key, algo='sha256', timedelta=30):
digestmod = getattr(hashlib, algo)
hash = hmac.HMAC(smart_bytes(key), digestmod=digestmod, msg=smart_bytes(s))
return hash.digest()
+
def get_wcs_services():
return settings.KNOWN_SERVICES.get('wcs')
+
def get_wcs_json(wcs_url, path, wcs_site, params={}):
if not wcs_url.endswith('/'):
wcs_url += '/'
@@ -70,13 +71,13 @@ def get_wcs_json(wcs_url, path, wcs_site, params={}):
response_json = cache.get(url)
if response_json is None:
signed_url = sign_url(url, wcs_site.get('secret'))
- response_json = requests.get(signed_url, headers={'accept': 'application/json'},
- timeout=10).json()
+ response_json = requests.get(signed_url, headers={'accept': 'application/json'}, timeout=10).json()
if not isinstance(response_json, dict):
response_json = {'data': response_json}
cache.set(url, response_json)
return response_json
+
def get_wcs_options(url, condition=None, params={}):
categories = {}
for wcs_key, wcs_site in get_wcs_services().items():
@@ -103,6 +104,7 @@ def get_wcs_options(url, condition=None, params={}):
options.append((category, sorted(categories[category], key=lambda x: x[1])))
return options
+
def get_wcs_formdef_details(formdef_reference):
wcs_key, form_slug = formdef_reference.split(':')
wcs_site = get_wcs_services()[wcs_key]
@@ -113,6 +115,7 @@ def get_wcs_formdef_details(formdef_reference):
return form
return None
+
def push_wcs_formdata(request, formdef_reference, context=None):
wcs_key, form_slug = formdef_reference.split(':')
wcs_site = get_wcs_services()[wcs_key]
@@ -121,7 +124,7 @@ def push_wcs_formdata(request, formdef_reference, context=None):
wcs_site_url += '/'
url = wcs_site_url + 'api/formdefs/%s/schema' % form_slug
response = requests.get(url)
- create_draft = not(bool('welco-direct' in (response.json().get('keywords') or '')))
+ create_draft = not (bool('welco-direct' in (response.json().get('keywords') or '')))
url = wcs_site_url + 'api/formdefs/%s/submit?' % form_slug
data = {
@@ -139,8 +142,7 @@ def push_wcs_formdata(request, formdef_reference, context=None):
url = sign_url(url, wcs_site.get('secret'))
- response = requests.post(url, data=json.dumps(data),
- headers={'Content-type': 'application/json'})
+ response = requests.post(url, data=json.dumps(data), headers={'Content-type': 'application/json'})
if response.json().get('err') != 0:
raise Exception('error %r' % response.content)
data = response.json()['data']
@@ -169,6 +171,7 @@ def get_wcs_data(endpoint, params=None):
json_response = {'data': json_response}
return json_response
+
def response_for_json(request, data):
json_str = json.dumps(data)
for variable in ('jsonpCallback', 'callback'):
diff --git a/welco/views.py b/welco/views.py
index 7fc6f95..0e69fa8 100644
--- a/welco/views.py
+++ b/welco/views.py
@@ -88,19 +88,22 @@ class Qualification(TemplateView):
context['source_pk'] = self.request.GET['source_pk']
if self.request.GET.get('source_pk'):
context['associations'] = Association.objects.filter(
- source_type=ContentType.objects.get(id=self.request.GET['source_type']),
- source_pk=self.request.GET['source_pk']).order_by('id')
+ source_type=ContentType.objects.get(id=self.request.GET['source_type']),
+ source_pk=self.request.GET['source_pk'],
+ ).order_by('id')
return context
def post(self, request, *args, **kwargs):
association = Association(
- source_type=ContentType.objects.get(id=request.POST['source_type']),
- source_pk=request.POST['source_pk'])
+ source_type=ContentType.objects.get(id=request.POST['source_type']),
+ source_pk=request.POST['source_pk'],
+ )
association.formdef_reference = request.POST['formdef_reference']
association.save()
request.GET = request.POST
return self.get(request)
+
qualification = csrf_exempt(Qualification.as_view())
@@ -117,8 +120,7 @@ class ChannelHome(TemplateView):
if not self.check_user_ok():
raise PermissionDenied()
context = super(ChannelHome, self).get_context_data(**kwargs)
- context['panels'] = [
- {'key': x, 'zone_url': x + '-zone'} for x in settings.SCREEN_PANELS]
+ context['panels'] = [{'key': x, 'zone_url': x + '-zone'} for x in settings.SCREEN_PANELS]
context['source'] = self.source_klass(self.request, **kwargs)
context['kb'] = KbHomeZone(self.request)
context['contacts'] = ContactsHomeZone(self.request)
@@ -141,20 +143,25 @@ def home(request):
return HttpResponseRedirect('%s/' % channel)
raise PermissionDenied()
+
class HomePhone(ChannelHome):
source_klass = PhoneHome
+
home_phone = login_required(HomePhone.as_view())
class HomeMail(ChannelHome):
source_klass = MailHome
+
home_mail = login_required(HomeMail.as_view())
+
class HomeCounter(ChannelHome):
source_klass = CounterHome
+
home_counter = login_required(HomeCounter.as_view())
@@ -174,11 +181,13 @@ def wcs_summary(request, *args, **kwargs):
break
return HttpResponse(json_str, content_type='application/javascript')
+
@login_required
def remove_association(request, *args, **kwargs):
Association.objects.filter(id=kwargs.get('pk')).delete()
return HttpResponseRedirect(resolve_url('home'))
+
@login_required
@csrf_exempt
def create_formdata(request, *args, **kwargs):
@@ -196,6 +205,7 @@ def create_formdata(request, *args, **kwargs):
json.dump({'result': 'ok', 'url': qualif.formdata_url}, response)
return response
+
@login_required
def menu_json(request):
response = HttpResponse(content_type='application/json')
@@ -209,17 +219,21 @@ def menu_json(request):
for channel in settings.CHANNEL_ROLES:
channel_groups = set(settings.CHANNEL_ROLES[channel])
if user_groups.intersection(channel_groups):
- menu.append({
- 'label': force_text(labels.get(channel)),
- 'slug': channel,
- 'url': request.build_absolute_uri(reverse('home-%s' % channel)),
- })
+ menu.append(
+ {
+ 'label': force_text(labels.get(channel)),
+ 'slug': channel,
+ 'url': request.build_absolute_uri(reverse('home-%s' % channel)),
+ }
+ )
if check_kb_user_perms(request.user, access=True):
- menu.append({
- 'label': force_text(_('Knowledge Base')),
- 'slug': 'book',
- 'url': request.build_absolute_uri(reverse('kb-home'))
- })
+ menu.append(
+ {
+ 'label': force_text(_('Knowledge Base')),
+ 'slug': 'book',
+ 'url': request.build_absolute_uri(reverse('kb-home')),
+ }
+ )
json_str = json.dumps(menu)
for variable in ('jsonpCallback', 'callback'):
if variable in request.GET:
diff --git a/welco/wsgi.py b/welco/wsgi.py
index 59a1867..4498d92 100644
--- a/welco/wsgi.py
+++ b/welco/wsgi.py
@@ -8,7 +8,9 @@ https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/
"""
import os
+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "welco.settings")
from django.core.wsgi import get_wsgi_application
+
application = get_wsgi_application()