transform and push form data to wcs (#9296)
This commit is contained in:
parent
e150ca6d12
commit
775a1f59b1
|
@ -0,0 +1,50 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('passerelle_paris_poc_gru', '0002_auto_20160225_0743'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='parispocgru',
|
||||
name='authentic_password',
|
||||
field=models.CharField(default='', max_length=64, verbose_name='Authentic password'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='parispocgru',
|
||||
name='authentic_username',
|
||||
field=models.CharField(default='', max_length=64, verbose_name='Authentic username'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='parispocgru',
|
||||
name='wcs_user_email',
|
||||
field=models.EmailField(default='', help_text='to authenticate against wcs', max_length=75, verbose_name='WCS user email'),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='parispocgru',
|
||||
name='consumer_key',
|
||||
field=models.CharField(default=None, max_length=128, verbose_name='Consumer Key'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='parispocgru',
|
||||
name='consumer_secret',
|
||||
field=models.CharField(default=None, max_length=128, verbose_name='Consumer Secret'),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='parispocgru',
|
||||
name='url',
|
||||
field=models.CharField(default=None, max_length=128, verbose_name='WebService Base Url'),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
|
@ -19,6 +19,7 @@ import requests
|
|||
from django.db import models
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db import models
|
||||
|
||||
from passerelle.base.models import BaseResource
|
||||
|
||||
|
@ -27,15 +28,16 @@ class ParisPocGru(BaseResource):
|
|||
url = models.CharField(max_length=128, blank=False,
|
||||
default="not provided", verbose_name=_('WebService Base Url')
|
||||
)
|
||||
|
||||
consumer_key = models.CharField(max_length=128, blank=False,
|
||||
default="not provided", verbose_name=_('Consumer Key')
|
||||
)
|
||||
|
||||
consumer_secret = models.CharField(max_length=128, blank=False,
|
||||
default="not provided", verbose_name=_('Consumer Secret')
|
||||
)
|
||||
|
||||
authentic_username = models.CharField(_('Authentic username'), max_length=64)
|
||||
authentic_password = models.CharField(_('Authentic password'), max_length=64)
|
||||
wcs_user_email = models.EmailField(_('WCS user email'),
|
||||
help_text=_('to authenticate against wcs'))
|
||||
category = _('Business Process Connectors')
|
||||
|
||||
class Meta:
|
||||
|
@ -71,4 +73,3 @@ class ParisPocGru(BaseResource):
|
|||
self.headers = {'Authorization': 'Bearer %s' %(self.access_token)}
|
||||
|
||||
return self.access_token
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2015-2016 Entr'ouvert
|
||||
#
|
||||
|
@ -16,20 +17,90 @@
|
|||
|
||||
import datetime
|
||||
import json
|
||||
import unicodedata
|
||||
import re
|
||||
import random
|
||||
import requests
|
||||
import time
|
||||
import logging
|
||||
|
||||
from django.core.files.storage import default_storage
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.views.generic.detail import SingleObjectMixin, DetailView
|
||||
from django.views.generic.edit import CreateView, UpdateView, DeleteView
|
||||
from django.views.generic.base import View
|
||||
from django.core.files.storage import default_storage
|
||||
from django.utils.http import urlencode
|
||||
from django.http import HttpResponse
|
||||
|
||||
from passerelle.base.signature import sign_url
|
||||
from passerelle import utils
|
||||
|
||||
from .models import ParisPocGru
|
||||
from .forms import ParisPocGruForm
|
||||
|
||||
demand_types = {
|
||||
1: u"demande d'information",
|
||||
2: u"reclamation"
|
||||
}
|
||||
|
||||
domains = {
|
||||
110: u"mairie",
|
||||
120: u"stationnement",
|
||||
100: u"autre",
|
||||
200: u"autre",
|
||||
210: u"Facil'familles"
|
||||
}
|
||||
|
||||
categories = {
|
||||
2: u"reservation de salle",
|
||||
3: u"autre",
|
||||
4: u"horaire de stationnement",
|
||||
5: u"autre",
|
||||
6: u"autre",
|
||||
7: u"problème tarifaire périscolaire",
|
||||
8: u"problème tarifaire petite enfance",
|
||||
9: u"autres"
|
||||
}
|
||||
|
||||
titles = {
|
||||
'1': u'Monsieur',
|
||||
'2': u'Madame'
|
||||
}
|
||||
|
||||
contact_mode = {
|
||||
1: u"mail",
|
||||
2: u"phone",
|
||||
3: u"mobile"
|
||||
}
|
||||
|
||||
fields_mapping = {
|
||||
'title': 'title',
|
||||
'last_name': 'last_name',
|
||||
'first_name': 'first_name',
|
||||
'email': 'email',
|
||||
'fixed_phone_number': 'fixed_phone_number',
|
||||
'mobile_phone_number': 'mobile_phone_number',
|
||||
'contact_mode': 'contact_mode',
|
||||
'comment': 'comment',
|
||||
'FFAccountNumber': 'family_number',
|
||||
'IncomeRevenue-Year-2': 'tax_bill',
|
||||
}
|
||||
|
||||
def get_authentic_site_url():
|
||||
return settings.KNOWN_SERVICES.get('authentic').items()[0][1]['url']
|
||||
|
||||
def simplify(s, space='-'):
|
||||
if s is None:
|
||||
return ''
|
||||
s = unicodedata.normalize('NFKD', s).encode('ascii', 'ignore')
|
||||
s = re.sub(r'[^\w\s\'%s]' % space, '', s).strip().lower()
|
||||
s = re.sub(r'[\s\'%s]+' % space, space, s)
|
||||
return s
|
||||
|
||||
|
||||
class ParisPocGruCreateView(CreateView):
|
||||
model = ParisPocGru
|
||||
form_class = ParisPocGruForm
|
||||
|
@ -55,7 +126,112 @@ class ParisPocGruDetailView(DetailView):
|
|||
class EndpointView(View, SingleObjectMixin):
|
||||
model = ParisPocGru
|
||||
|
||||
def get_user(self, data):
|
||||
logger = logging.getLogger(__name__)
|
||||
a2_url = get_authentic_site_url() + 'api/users/'
|
||||
headers={'Content-type': 'application/json'}
|
||||
auth = (self.object.authentic_username, self.object.authentic_password)
|
||||
kwargs = {'headers': headers, 'auth': auth}
|
||||
uid = data['guid'].replace('-', '')
|
||||
r = requests.get(a2_url + uid, **kwargs)
|
||||
result = r.json()
|
||||
if 'email' in result:
|
||||
logger.debug('user %r found', result['email'])
|
||||
return result
|
||||
data = {'password': str(random.SystemRandom().random()),
|
||||
'first_name': data['first_name'],
|
||||
'last_name': data['last_name'],
|
||||
'email': data['email'],
|
||||
'username': uid,
|
||||
'uuid': uid,
|
||||
'title': data['title'],
|
||||
'phone': data.get('fixed_phone_number'),
|
||||
'mobile': data.get('mobile_phone_number')
|
||||
}
|
||||
r = requests.post(a2_url, data=json.dumps(data),
|
||||
**kwargs)
|
||||
logger.debug('user %r created', result['email'])
|
||||
return r.json()
|
||||
|
||||
def sign_wcs_url(self, endpoint):
|
||||
wcs_site = settings.KNOWN_SERVICES.get('wcs').items()[0][1]
|
||||
params = {'orig': wcs_site['orig'], 'email': self.object.wcs_user_email}
|
||||
url = wcs_site['url'] + endpoint
|
||||
url += '?' + urlencode(params)
|
||||
return sign_url(url, wcs_site.get('secret'))
|
||||
|
||||
|
||||
def create_demand(self, data):
|
||||
logger = logging.getLogger(__name__)
|
||||
self.object = self.get_object()
|
||||
data = data['ticket']
|
||||
user = self.get_user(data.pop('user'))
|
||||
extra_fields = data.pop('extra_fields')
|
||||
demand_type = data.get('type')
|
||||
domain = data.get('domain')
|
||||
category = data.get('category')
|
||||
|
||||
# compute form slug from input data
|
||||
assert demand_type in demand_types
|
||||
form_slug = demand_types[demand_type]
|
||||
assert domain in domains
|
||||
form_slug += ' ' + domains[domain]
|
||||
assert category in categories
|
||||
form_slug += ' ' + categories[category]
|
||||
logger.debug('posting to form "%r"', simplify(form_slug))
|
||||
|
||||
extra_fields = dict([(item['field'], {'metadata': item.get('metadata'),
|
||||
'value': item['value']}) for item in extra_fields])
|
||||
data.update(extra_fields)
|
||||
user_uuid = user.get('uuid')
|
||||
for i in xrange(50):
|
||||
try:
|
||||
r = requests.get(self.sign_wcs_url('api/users/%s/' % user_uuid))
|
||||
user_data = r.json()
|
||||
r.raise_for_status()
|
||||
break
|
||||
except requests.HTTPError as e:
|
||||
if e.response.status_code != 404:
|
||||
raise
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
# return gateway timeout if no user provisionned
|
||||
return HttpResponse(status=504)
|
||||
|
||||
formdata = {}
|
||||
for f, k in fields_mapping.iteritems():
|
||||
if f == 'title':
|
||||
d = titles[user.get(f)]
|
||||
formdata['%s_raw' % k] = user.get(f)
|
||||
elif f == 'contact_mode':
|
||||
d = contact_mode[data.get(f)]
|
||||
formdata['%s_raw' % k] = data.get(f)
|
||||
elif f == 'IncomeRevenue-Year-2' and data.get(f):
|
||||
metadata = dict([(item['name'], item['value']) for item in data.get(f, {}).get('metadata', [])])
|
||||
if metadata:
|
||||
d = {'filename': metadata['filename'],
|
||||
'content': data.get(f, {}).get('value'),
|
||||
'content_type': metadata['mimetype']}
|
||||
else:
|
||||
d = data.get(f, user.get(f))
|
||||
if not d:
|
||||
continue
|
||||
if 'value' in d:
|
||||
d = d['value']
|
||||
formdata[str(k)] = d
|
||||
data = {
|
||||
'data': formdata,
|
||||
'context': {'user_id': user_data['id']}
|
||||
}
|
||||
url = self.sign_wcs_url('api/formdefs/%s/submit' % simplify(form_slug))
|
||||
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)
|
||||
return response.json()['data']['id']
|
||||
|
||||
@method_decorator(csrf_exempt)
|
||||
@utils.to_json('api')
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
filename = 'paris-poc-gru-dump-%s.txt' % self.get_object().slug
|
||||
with default_storage.open(filename, mode='a') as fp:
|
||||
|
@ -65,4 +241,4 @@ class EndpointView(View, SingleObjectMixin):
|
|||
'qs': request.environ.get('QUERY_STRING'),
|
||||
'body': request.body,
|
||||
})
|
||||
return utils.response_for_json(request, {})
|
||||
return self.create_demand(json.loads(request.body))
|
||||
|
|
Reference in New Issue