1
|
import urllib
|
2
|
import urllib2
|
3
|
import urlparse
|
4
|
import json
|
5
|
import base64
|
6
|
import datetime
|
7
|
|
8
|
from quixote import get_publisher, get_request, redirect, get_response, get_session_manager, get_session
|
9
|
from quixote.directory import AccessControlled, Directory
|
10
|
from quixote.html import TemplateIO, htmltext
|
11
|
|
12
|
import qommon.form
|
13
|
from qommon.misc import http_post_request, http_get_page
|
14
|
|
15
|
|
16
|
class MSPDirectory(Directory):
|
17
|
_q_exports = ['', 'pick', 'download']
|
18
|
|
19
|
@property
|
20
|
def msp_gateway_base_url(self):
|
21
|
return get_publisher().get_site_option('msp')
|
22
|
|
23
|
@property
|
24
|
def authorize_url(self):
|
25
|
return urlparse.urljoin(self.msp_gateway_base_url, 'authorize/')
|
26
|
|
27
|
@property
|
28
|
def access_token_url(self):
|
29
|
return urlparse.urljoin(self.msp_gateway_base_url, 'access_token/')
|
30
|
|
31
|
@property
|
32
|
def documents_url(self):
|
33
|
return urlparse.urljoin(self.msp_gateway_base_url, 'documents/')
|
34
|
|
35
|
@property
|
36
|
def document_url(self):
|
37
|
return urlparse.urljoin(self.msp_gateway_base_url, 'documents/%s/')
|
38
|
|
39
|
@property
|
40
|
def client_id(self):
|
41
|
return get_publisher().get_site_option('msp_client_id')
|
42
|
|
43
|
@property
|
44
|
def client_secret(self):
|
45
|
return get_publisher().get_site_option('msp_client_secret')
|
46
|
|
47
|
def fix_document(self, document):
|
48
|
site_charset = get_publisher().site_charset
|
49
|
for key, value in document.iteritems():
|
50
|
# date are returned as millisecond POSIX timestamp,
|
51
|
# it should be ISO-8601 instead
|
52
|
if key.endswith('Date') and value is not None:
|
53
|
document[key] = unicode(datetime.date.fromtimestamp(value // 1000))
|
54
|
value = document[key] = document[key].replace(u'-', u'\u2011')
|
55
|
if isinstance(value, unicode) and key != 'content':
|
56
|
document[key] = value.encode(site_charset)
|
57
|
|
58
|
def get_documents(self, access_token):
|
59
|
response, status, content, auth_header = http_get_page(self.documents_url, {
|
60
|
'Authorization': 'Bearer %s' % access_token,
|
61
|
});
|
62
|
documents = json.loads(content)
|
63
|
for document in documents:
|
64
|
self.fix_document(document)
|
65
|
return documents
|
66
|
|
67
|
def get_document(self, doc_id, access_token):
|
68
|
response, status, content, auth_header = http_get_page(
|
69
|
self.document_url % doc_id,
|
70
|
{ 'Authorization': 'Bearer %s' % access_token, }
|
71
|
);
|
72
|
document = json.loads(content)
|
73
|
self.fix_document(document)
|
74
|
return document
|
75
|
|
76
|
def authorize(self, self_url, scope):
|
77
|
params = {
|
78
|
'redirect_uri': self_url,
|
79
|
'response_type': 'code',
|
80
|
'scope': scope,
|
81
|
}
|
82
|
return redirect('%s?%s' % (
|
83
|
self.authorize_url, urllib.urlencode(params)))
|
84
|
|
85
|
def access_token(self, self_url, code):
|
86
|
params = {
|
87
|
'code': code,
|
88
|
'client_id': self.client_id,
|
89
|
'client_secret': self.client_secret,
|
90
|
'grant_type': 'authorization_code',
|
91
|
'redirect_uri': self_url,
|
92
|
}
|
93
|
response, status, data, auth_header = http_post_request(self.access_token_url,
|
94
|
urllib.urlencode(params), { 'Content-Type': 'application/x-www-form-urlencoded' })
|
95
|
return json.loads(data)['access_token']
|
96
|
|
97
|
def pick (self):
|
98
|
request = get_request()
|
99
|
frontoffice_url = get_publisher().get_frontoffice_url()
|
100
|
self_url = frontoffice_url
|
101
|
self_url += '/msp/pick'
|
102
|
self_url = self_url.replace('://', '://iframe-')
|
103
|
|
104
|
if 'code' not in request.form and 'error' not in request.form:
|
105
|
return self.authorize(self_url, 'LIST_DOCS')
|
106
|
access_token = self.access_token(self_url, request.form['code'])
|
107
|
return self.pick_display(access_token)
|
108
|
|
109
|
def pick_display(self, access_token):
|
110
|
r = TemplateIO(html=True)
|
111
|
|
112
|
request = get_request()
|
113
|
|
114
|
get_response().add_javascript(['jquery.js',
|
115
|
'tablesorter/jquery.tablesorter.min.js'])
|
116
|
get_response().add_javascript_code(
|
117
|
str('''$(function() { $("table.sortable").tablesorter(); });'''))
|
118
|
get_response().add_css_include('../js/tablesorter/themes/blue/style.css')
|
119
|
|
120
|
frontoffice_url = get_publisher().get_frontoffice_url()
|
121
|
|
122
|
r += htmltext('<h2>%s</h2>') % _('Pick a file')
|
123
|
|
124
|
if 'error' not in request.form:
|
125
|
documents = self.get_documents(access_token)
|
126
|
r += htmltext('<table id="msp-pick-file-table" class="sortable tablesorter">')
|
127
|
r += htmltext('<thead>')
|
128
|
r += htmltext('<tr>')
|
129
|
r += htmltext('<th>%s</th>') % _('Filename')
|
130
|
r += htmltext('<th>%s</th>') % _('Expiration date')
|
131
|
r += htmltext('</tr>')
|
132
|
r += htmltext('</thead>')
|
133
|
r += htmltext('<tbody>')
|
134
|
for document in documents:
|
135
|
r += htmltext('<tr>')
|
136
|
for key in ('name', 'expirationDate'):
|
137
|
r += htmltext('<td class="msp-pick-file-table-%s">' % key)
|
138
|
if key == 'name':
|
139
|
r += htmltext('<a href="%s/msp/download?doc_id=%s">' % \
|
140
|
(frontoffice_url, document['id']))
|
141
|
r += '%s' % (document[key] or '')
|
142
|
if key == 'name':
|
143
|
r += htmltext('</a>')
|
144
|
r += htmltext('</td>')
|
145
|
r += htmltext('</tr>')
|
146
|
r += htmltext('</tbody>')
|
147
|
r += htmltext('</table>')
|
148
|
else:
|
149
|
r += htmltext('<p>%s</p>') % _('Unable to access your mon.Service-Public.fr documents')
|
150
|
return r.getvalue()
|
151
|
|
152
|
def set_token(self, token, title):
|
153
|
get_response().add_javascript(['jquery.js'])
|
154
|
get_response().page_template_key = 'iframe'
|
155
|
r = TemplateIO(html=True)
|
156
|
r += htmltext('<html><body>')
|
157
|
r += htmltext('<pre>Token: %s</pre>') % token
|
158
|
r += htmltext('<script>window.top.document.set_token("%s", "%s");</script>' % (
|
159
|
token, title))
|
160
|
r += htmltext('</body></html>')
|
161
|
return r.getvalue()
|
162
|
|
163
|
def download(self):
|
164
|
request = get_request()
|
165
|
assert 'doc_id' in request.form
|
166
|
doc_id = request.form['doc_id']
|
167
|
frontoffice_url = get_publisher().get_frontoffice_url()
|
168
|
self_url = frontoffice_url
|
169
|
self_url += '/msp/download?%s' % urllib.urlencode({'doc_id': doc_id})
|
170
|
if 'code' not in request.form and 'error' not in request.form:
|
171
|
return self.authorize(self_url, 'GET_DOC')
|
172
|
if 'error' in request.form:
|
173
|
return self.set_token('', '')
|
174
|
else:
|
175
|
access_token = self.access_token(self_url, request.form['code'])
|
176
|
document = self.get_document(doc_id, access_token)
|
177
|
download = qommon.form.PicklableUpload(document['name'],
|
178
|
content_type='application/pdf')
|
179
|
download.__setstate__({
|
180
|
'data': base64.b64decode(document['content']),
|
181
|
})
|
182
|
token = get_session().add_tempfile(download)
|
183
|
return self.set_token(token, document['name'])
|