1
|
from quixote import get_publisher, get_response, get_request, redirect, get_session
|
2
|
from quixote.directory import Directory
|
3
|
from quixote.html import TemplateIO, htmltext
|
4
|
|
5
|
from wcs.qommon import _
|
6
|
from wcs.qommon.misc import get_variadic_url, simplify
|
7
|
|
8
|
import os
|
9
|
import re
|
10
|
import string
|
11
|
|
12
|
from django.utils.six.moves.urllib import parse as urlparse
|
13
|
|
14
|
try:
|
15
|
import lasso
|
16
|
except ImportError:
|
17
|
pass
|
18
|
|
19
|
import wcs
|
20
|
import wcs.root
|
21
|
from wcs import qommon
|
22
|
from wcs.forms.root import RootDirectory as FormsRootDirectory
|
23
|
from wcs.qommon import get_cfg, get_logger
|
24
|
from wcs.qommon import template
|
25
|
from wcs.qommon import errors
|
26
|
from wcs.qommon.form import *
|
27
|
from wcs.qommon import logger
|
28
|
from wcs.roles import logged_users_role
|
29
|
|
30
|
from wcs.qommon import emails
|
31
|
from wcs.qommon.sms import SMS
|
32
|
from wcs.categories import Category
|
33
|
from wcs.formdef import FormDef
|
34
|
from wcs.data_sources import NamedDataSource
|
35
|
from wcs.qommon.tokens import Token
|
36
|
from wcs.qommon.admin.emails import EmailsDirectory
|
37
|
from wcs.qommon.admin.texts import TextsDirectory
|
38
|
|
39
|
from .myspace import MyspaceDirectory
|
40
|
from .payments import PublicPaymentDirectory
|
41
|
from .payments_ui import InvoicesDirectory
|
42
|
|
43
|
from . import admin
|
44
|
|
45
|
import wcs.forms.root
|
46
|
from wcs.workflows import Workflow
|
47
|
from wcs.forms.preview import PreviewDirectory
|
48
|
|
49
|
from .saml2 import Saml2Directory
|
50
|
|
51
|
OldRootDirectory = wcs.root.RootDirectory
|
52
|
|
53
|
import wcs.qommon.ident.password
|
54
|
import wcs.qommon.ident.idp
|
55
|
|
56
|
|
57
|
def category_get_homepage_position(self):
|
58
|
if hasattr(self, 'homepage_position') and self.homepage_position:
|
59
|
return self.homepage_position
|
60
|
if self.url_name == 'consultations':
|
61
|
return '2nd'
|
62
|
return '1st'
|
63
|
Category.get_homepage_position = category_get_homepage_position
|
64
|
|
65
|
def category_get_limit(self):
|
66
|
if hasattr(self, 'limit') and self.limit is not None:
|
67
|
return self.limit
|
68
|
return 7
|
69
|
Category.get_limit = category_get_limit
|
70
|
|
71
|
Category.TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'homepage_position']
|
72
|
Category.INT_ATTRIBUTES = ['position', 'limit']
|
73
|
|
74
|
OldRegisterDirectory = wcs.root.RegisterDirectory
|
75
|
|
76
|
class AlternateRegisterDirectory(OldRegisterDirectory):
|
77
|
def _q_traverse(self, path):
|
78
|
get_response().filter['bigdiv'] = 'new_member'
|
79
|
return OldRegisterDirectory._q_traverse(self, path)
|
80
|
|
81
|
def _q_index(self):
|
82
|
get_logger().info('register')
|
83
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
84
|
|
85
|
if len(ident_methods) == 0:
|
86
|
idps = get_cfg('idp', {})
|
87
|
if len(idps) == 0:
|
88
|
return template.error_page(_('Authentication subsystem is not yet configured.'))
|
89
|
ident_methods = ['idp'] # fallback to old behaviour; saml.
|
90
|
|
91
|
if len(ident_methods) == 1:
|
92
|
method = ident_methods[0]
|
93
|
else:
|
94
|
method = 'password'
|
95
|
|
96
|
return wcs.qommon.ident.register(method)
|
97
|
|
98
|
OldLoginDirectory = wcs.root.LoginDirectory
|
99
|
|
100
|
class AlternateLoginDirectory(OldLoginDirectory):
|
101
|
def _q_traverse(self, path):
|
102
|
get_response().filter['bigdiv'] = 'member'
|
103
|
return OldLoginDirectory._q_traverse(self, path)
|
104
|
|
105
|
def _q_index(self):
|
106
|
get_logger().info('login')
|
107
|
ident_methods = get_cfg('identification', {}).get('methods', [])
|
108
|
|
109
|
if get_request().form.get('ReturnUrl'):
|
110
|
get_request().form['next'] = get_request().form.pop('ReturnUrl')
|
111
|
|
112
|
if 'IsPassive' in get_request().form and 'idp' in ident_methods:
|
113
|
# if isPassive is given in query parameters, we restrict ourselves
|
114
|
# to saml login.
|
115
|
ident_methods = ['idp']
|
116
|
|
117
|
if len(ident_methods) > 1 and 'idp' in ident_methods:
|
118
|
# if there is more than one identification method, and there is a
|
119
|
# possibility of SSO, if we got there as a consequence of an access
|
120
|
# unauthorized url on admin/ or backoffice/, then idp auth method
|
121
|
# is chosen forcefully.
|
122
|
after_url = get_request().form.get('next')
|
123
|
if after_url:
|
124
|
root_url = get_publisher().get_root_url()
|
125
|
after_path = urlparse.urlparse(after_url)[2]
|
126
|
after_path = after_path[len(root_url):]
|
127
|
if after_path.startswith(str('admin')) or \
|
128
|
after_path.startswith(str('backoffice')):
|
129
|
ident_methods = ['idp']
|
130
|
|
131
|
# don't display authentication system choice
|
132
|
if len(ident_methods) == 1:
|
133
|
method = ident_methods[0]
|
134
|
try:
|
135
|
return wcs.qommon.ident.login(method)
|
136
|
except KeyError:
|
137
|
get_logger().error('failed to login with method %s' % method)
|
138
|
return errors.TraversalError()
|
139
|
|
140
|
if sorted(ident_methods) == ['idp', 'password']:
|
141
|
r = TemplateIO(html=True)
|
142
|
get_response().breadcrumb.append(('login', _('Login')))
|
143
|
identities_cfg = get_cfg('identities', {})
|
144
|
form = Form(enctype = 'multipart/form-data', id = 'login-form', use_tokens = False)
|
145
|
if identities_cfg.get('email-as-username', False):
|
146
|
form.add(StringWidget, 'username', title = _('Email'), size=25, required=True)
|
147
|
else:
|
148
|
form.add(StringWidget, 'username', title = _('Username'), size=25, required=True)
|
149
|
form.add(PasswordWidget, 'password', title = _('Password'), size=25, required=True)
|
150
|
form.add_submit('submit', _('Connect'))
|
151
|
if form.is_submitted() and not form.has_errors():
|
152
|
tmp = wcs.qommon.ident.password.MethodDirectory().login_submit(form)
|
153
|
if not form.has_errors():
|
154
|
return tmp
|
155
|
|
156
|
r += htmltext('<div id="login-password">')
|
157
|
r += get_session().display_message()
|
158
|
r += form.render()
|
159
|
|
160
|
base_url = get_publisher().get_root_url()
|
161
|
r += htmltext('<p><a href="%sident/password/forgotten">%s</a></p>') % (
|
162
|
base_url, _('Forgotten password ?'))
|
163
|
|
164
|
r += htmltext('</div>')
|
165
|
|
166
|
# XXX: this part only supports a single IdP
|
167
|
r += htmltext('<div id="login-sso">')
|
168
|
r += TextsDirectory.get_html_text('aq-sso-text')
|
169
|
form = Form(enctype='multipart/form-data',
|
170
|
action = '%sident/idp/login' % base_url)
|
171
|
form.add_hidden('method', 'idp')
|
172
|
for kidp, idp in get_cfg('idp', {}).items():
|
173
|
p = lasso.Provider(lasso.PROVIDER_ROLE_IDP,
|
174
|
misc.get_abs_path(idp['metadata']),
|
175
|
misc.get_abs_path(idp.get('publickey')), None)
|
176
|
form.add_hidden('idp', p.providerId)
|
177
|
break
|
178
|
form.add_submit('submit', _('Connect'))
|
179
|
|
180
|
r += form.render()
|
181
|
r += htmltext('</div>')
|
182
|
|
183
|
get_request().environ['REQUEST_METHOD'] = 'GET'
|
184
|
|
185
|
r += htmltext("""<script type="text/javascript">
|
186
|
document.getElementById('login-form')['username'].focus();
|
187
|
</script>""")
|
188
|
return r.getvalue()
|
189
|
else:
|
190
|
return OldLoginDirectory._q_index(self)
|
191
|
|
192
|
|
193
|
OldIdentDirectory = wcs.root.IdentDirectory
|
194
|
class AlternateIdentDirectory(OldIdentDirectory):
|
195
|
def _q_traverse(self, path):
|
196
|
get_response().filter['bigdiv'] = 'member'
|
197
|
return OldIdentDirectory._q_traverse(self, path)
|
198
|
|
199
|
|
200
|
class AlternatePreviewDirectory(PreviewDirectory):
|
201
|
def _q_traverse(self, path):
|
202
|
get_response().filter['bigdiv'] = 'rub_service'
|
203
|
return super(AlternatePreviewDirectory, self)._q_traverse(path)
|
204
|
|
205
|
|
206
|
class AlternateRootDirectory(OldRootDirectory):
|
207
|
_q_exports = ['', 'admin', 'backoffice', 'forms', 'login', 'logout',
|
208
|
'saml', 'register', 'ident', 'afterjobs',
|
209
|
('informations-editeur', 'informations_editeur'),
|
210
|
'myspace', 'services', 'categories', 'user',
|
211
|
('tmp-upload', 'tmp_upload'), 'json', '__version__',
|
212
|
'themes', 'pages', 'payment', 'invoices', 'roles',
|
213
|
'api', 'code', 'fargo', 'tryauth', 'auth', 'preview',
|
214
|
('reload-top', 'reload_top'), 'static',
|
215
|
('i18n.js', 'i18n_js'), 'actions',]
|
216
|
|
217
|
register = AlternateRegisterDirectory()
|
218
|
login = AlternateLoginDirectory()
|
219
|
ident = AlternateIdentDirectory()
|
220
|
myspace = MyspaceDirectory()
|
221
|
saml = Saml2Directory()
|
222
|
payment = PublicPaymentDirectory()
|
223
|
invoices = InvoicesDirectory()
|
224
|
code = wcs.forms.root.TrackingCodesDirectory()
|
225
|
preview = AlternatePreviewDirectory()
|
226
|
|
227
|
def get_substitution_variables(self):
|
228
|
return {'links': ''}
|
229
|
|
230
|
def _q_traverse(self, path):
|
231
|
self.feed_substitution_parts()
|
232
|
|
233
|
# set app_label to Publik if none was specified (this is used in
|
234
|
# backoffice header top line)
|
235
|
if not get_publisher().get_site_option('app_label'):
|
236
|
if not get_publisher().site_options.has_section('options'):
|
237
|
get_publisher().site_options.add_section('options')
|
238
|
get_publisher().site_options.set('options', 'app_label', 'Publik')
|
239
|
|
240
|
response = get_response()
|
241
|
if not hasattr(response, 'filter'):
|
242
|
response.filter = {}
|
243
|
|
244
|
response.filter['auquotidien'] = True
|
245
|
if not path or (path[0] not in ('api', 'backoffice') and not get_request().is_json()):
|
246
|
# api & backoffice have no use for a side box
|
247
|
response.filter['gauche'] = self.box_side(path)
|
248
|
response.filter['keywords'] = template.get_current_theme().get('keywords')
|
249
|
get_publisher().substitutions.feed(self)
|
250
|
|
251
|
response.breadcrumb = [ ('', _('Home')) ]
|
252
|
|
253
|
if not self.admin:
|
254
|
self.admin = get_publisher().admin_directory_class()
|
255
|
|
256
|
if not self.backoffice:
|
257
|
self.backoffice = get_publisher().backoffice_directory_class()
|
258
|
|
259
|
try:
|
260
|
return Directory._q_traverse(self, path)
|
261
|
except errors.TraversalError as e:
|
262
|
try:
|
263
|
f = FormDef.get_by_urlname(path[0])
|
264
|
except KeyError:
|
265
|
pass
|
266
|
else:
|
267
|
base_url = get_publisher().get_root_url()
|
268
|
|
269
|
uri_rest = get_request().environ.get('REQUEST_URI')
|
270
|
if not uri_rest:
|
271
|
# REQUEST_URI doesn't exist when using internal HTTP server
|
272
|
# (--http)
|
273
|
uri_rest = get_request().get_path()
|
274
|
if get_request().get_query():
|
275
|
uri_rest += '?' + get_request().get_query()
|
276
|
if uri_rest.startswith(base_url):
|
277
|
uri_rest = uri_rest[len(base_url):]
|
278
|
if f.category:
|
279
|
if f.category.url_name == f.url_name:
|
280
|
return FormsRootDirectory(f.category)._q_traverse(path[1:])
|
281
|
return redirect('%s%s/%s' % (base_url, f.category.url_name, uri_rest))
|
282
|
|
283
|
raise e
|
284
|
|
285
|
|
286
|
def _q_lookup(self, component):
|
287
|
# is this a category ?
|
288
|
try:
|
289
|
category = Category.get_by_urlname(component)
|
290
|
except KeyError:
|
291
|
category = None
|
292
|
|
293
|
# is this a formdef ?
|
294
|
try:
|
295
|
formdef = FormDef.get_by_urlname(component)
|
296
|
except KeyError:
|
297
|
if category:
|
298
|
return FormsRootDirectory(category)
|
299
|
else:
|
300
|
# if the form has no category, or the request is a POST, or the
|
301
|
# slug matches both a category and a formdef, directly call
|
302
|
# into FormsRootDirectory.
|
303
|
if formdef.category_id is None or get_request().get_method() == 'POST' or (
|
304
|
formdef and category):
|
305
|
get_response().filter['bigdiv'] = 'rub_service'
|
306
|
return FormsRootDirectory()._q_lookup(component)
|
307
|
|
308
|
# if there is category, let it fall back to raise TraversalError,
|
309
|
# it will get caught in _q_traverse that will redirect it to an
|
310
|
# URL embedding the category
|
311
|
|
312
|
if component in ('accessibility', 'contact', 'help'):
|
313
|
if TextsDirectory.get_html_text('aq-' + component):
|
314
|
return getattr(self, component)()
|
315
|
|
316
|
return None
|
317
|
|
318
|
def json(self):
|
319
|
return FormsRootDirectory().json()
|
320
|
|
321
|
def categories(self):
|
322
|
return FormsRootDirectory().categories()
|
323
|
|
324
|
def _q_index(self):
|
325
|
if get_request().is_json():
|
326
|
return FormsRootDirectory().json()
|
327
|
|
328
|
root_url = get_publisher().get_root_url()
|
329
|
if get_request().user and get_request().user.anonymous and get_request().user.lasso_dump:
|
330
|
return redirect('%smyspace/new' % root_url)
|
331
|
|
332
|
redirect_url = get_cfg('misc', {}).get('homepage-redirect-url')
|
333
|
if redirect_url:
|
334
|
return redirect(misc.get_variadic_url(redirect_url,
|
335
|
get_publisher().substitutions.get_context_variables()))
|
336
|
|
337
|
template.html_top()
|
338
|
r = TemplateIO(html=True)
|
339
|
get_response().filter['is_index'] = True
|
340
|
|
341
|
if not 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
|
342
|
t = TextsDirectory.get_html_text('aq-home-page')
|
343
|
if not t:
|
344
|
if get_request().user:
|
345
|
t = TextsDirectory.get_html_text('welcome-logged')
|
346
|
else:
|
347
|
t = TextsDirectory.get_html_text('welcome-unlogged')
|
348
|
if t:
|
349
|
r += htmltext('<div id="home-page-intro">')
|
350
|
r += t
|
351
|
r += htmltext('</div>')
|
352
|
|
353
|
r += htmltext('<div id="centre">')
|
354
|
r += self.box_services(position='1st')
|
355
|
r += htmltext('</div>')
|
356
|
r += htmltext('<div id="droite">')
|
357
|
r += self.myspace_snippet()
|
358
|
r += self.box_services(position='2nd')
|
359
|
r += self.consultations()
|
360
|
r += htmltext('</div>')
|
361
|
|
362
|
user = get_request().user
|
363
|
if user and user.can_go_in_backoffice():
|
364
|
get_response().filter['backoffice'] = True
|
365
|
|
366
|
return r.getvalue()
|
367
|
|
368
|
def services(self):
|
369
|
template.html_top()
|
370
|
get_response().filter['bigdiv'] = 'rub_service'
|
371
|
return self.box_services(level = 2)
|
372
|
|
373
|
def box_services(self, level=3, position=None):
|
374
|
## Services
|
375
|
if get_request().user and get_request().user.roles:
|
376
|
accepted_roles = get_request().user.roles
|
377
|
else:
|
378
|
accepted_roles = []
|
379
|
|
380
|
cats = Category.select(order_by = 'name')
|
381
|
cats = [x for x in cats if x.url_name != 'consultations']
|
382
|
Category.sort_by_position(cats)
|
383
|
|
384
|
all_formdefs = FormDef.select(lambda x: not x.is_disabled() or x.disabled_redirection,
|
385
|
order_by = 'name')
|
386
|
|
387
|
if position:
|
388
|
t = self.display_list_of_formdefs(
|
389
|
[x for x in cats if x.get_homepage_position() == position],
|
390
|
all_formdefs, accepted_roles)
|
391
|
else:
|
392
|
t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles)
|
393
|
|
394
|
if not t:
|
395
|
return
|
396
|
|
397
|
r = TemplateIO(html=True)
|
398
|
|
399
|
if position == '2nd':
|
400
|
r += htmltext('<div id="services-2nd">')
|
401
|
else:
|
402
|
r += htmltext('<div id="services">')
|
403
|
if level == 2:
|
404
|
r += htmltext('<h2>%s</h2>') % _('Services')
|
405
|
else:
|
406
|
r += htmltext('<h3>%s</h3>') % _('Services')
|
407
|
|
408
|
if 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
|
409
|
homepage_text = TextsDirectory.get_html_text('aq-home-page')
|
410
|
if homepage_text:
|
411
|
r += htmltext('<div id="home-page-intro">')
|
412
|
r += homepage_text
|
413
|
r += htmltext('</div>')
|
414
|
|
415
|
r += htmltext('<ul>')
|
416
|
r += t
|
417
|
r += htmltext('</ul>')
|
418
|
|
419
|
r += htmltext('</div>')
|
420
|
return r.getvalue()
|
421
|
|
422
|
def display_list_of_formdefs(self, cats, all_formdefs, accepted_roles):
|
423
|
r = TemplateIO(html=True)
|
424
|
for category in cats:
|
425
|
if category.url_name == 'consultations':
|
426
|
self.consultations_category = category
|
427
|
continue
|
428
|
formdefs = [x for x in all_formdefs if str(x.category_id) == str(category.id)]
|
429
|
formdefs_advertise = []
|
430
|
|
431
|
for formdef in formdefs[:]:
|
432
|
if formdef.is_disabled(): # is a redirection
|
433
|
continue
|
434
|
if not formdef.roles:
|
435
|
continue
|
436
|
if not get_request().user:
|
437
|
if formdef.always_advertise:
|
438
|
formdefs_advertise.append(formdef)
|
439
|
formdefs.remove(formdef)
|
440
|
continue
|
441
|
if logged_users_role().id in formdef.roles:
|
442
|
continue
|
443
|
for q in accepted_roles:
|
444
|
if q in formdef.roles:
|
445
|
break
|
446
|
else:
|
447
|
if formdef.always_advertise:
|
448
|
formdefs_advertise.append(formdef)
|
449
|
formdefs.remove(formdef)
|
450
|
|
451
|
if not formdefs and not formdefs_advertise:
|
452
|
continue
|
453
|
|
454
|
keywords = {}
|
455
|
for formdef in formdefs:
|
456
|
for keyword in formdef.keywords_list:
|
457
|
keywords[keyword] = True
|
458
|
|
459
|
r += htmltext('<li id="category-%s" data-keywords="%s">') % (
|
460
|
category.url_name, ' '.join(keywords))
|
461
|
r += htmltext('<strong>')
|
462
|
r += htmltext('<a href="%s/">') % category.url_name
|
463
|
r += category.name
|
464
|
r += htmltext('</a></strong>\n')
|
465
|
r += category.get_description_html_text()
|
466
|
r += htmltext('<ul>')
|
467
|
limit = category.get_limit()
|
468
|
for formdef in formdefs[:limit]:
|
469
|
r += htmltext('<li data-keywords="%s">') % ' '.join(formdef.keywords_list)
|
470
|
classes = []
|
471
|
if formdef.is_disabled() and formdef.disabled_redirection:
|
472
|
classes.append('redirection')
|
473
|
r += htmltext('<a class="%s" href="%s/%s/">%s</a>') % (
|
474
|
' '.join(classes), category.url_name, formdef.url_name, formdef.name)
|
475
|
r += htmltext('</li>\n')
|
476
|
if len(formdefs) < limit:
|
477
|
for formdef in formdefs_advertise[:limit-len(formdefs)]:
|
478
|
r += htmltext('<li class="required-authentication">')
|
479
|
r += htmltext('<a href="%s/%s/">%s</a>') % (category.url_name, formdef.url_name, formdef.name)
|
480
|
r += htmltext('<span> (%s)</span>') % _('authentication required')
|
481
|
r += htmltext('</li>\n')
|
482
|
if (len(formdefs)+len(formdefs_advertise)) > limit:
|
483
|
r += htmltext('<li class="all-forms"><a href="%s/" title="%s">%s</a></li>') % (category.url_name,
|
484
|
_('Access to all forms of the "%s" category') % category.name,
|
485
|
_('Access to all forms in this category'))
|
486
|
r += htmltext('</ul>')
|
487
|
r += htmltext('</li>\n')
|
488
|
|
489
|
return r.getvalue()
|
490
|
|
491
|
def consultations(self):
|
492
|
cats = [x for x in Category.select() if x.url_name == 'consultations']
|
493
|
if not cats:
|
494
|
return
|
495
|
consultations_category = cats[0]
|
496
|
formdefs = FormDef.select(lambda x: (
|
497
|
str(x.category_id) == str(consultations_category.id) and
|
498
|
(not x.is_disabled() or x.disabled_redirection)),
|
499
|
order_by = 'name')
|
500
|
if not formdefs:
|
501
|
return
|
502
|
## Consultations
|
503
|
r = TemplateIO(html=True)
|
504
|
r += htmltext('<div id="consultations">')
|
505
|
r += htmltext('<h3>%s</h3>') % _('Consultations')
|
506
|
r += consultations_category.get_description_html_text()
|
507
|
r += htmltext('<ul>')
|
508
|
for formdef in formdefs:
|
509
|
r += htmltext('<li>')
|
510
|
r += htmltext('<a href="%s/%s/">%s</a>') % (consultations_category.url_name,
|
511
|
formdef.url_name, formdef.name)
|
512
|
r += htmltext('</li>')
|
513
|
r += htmltext('</ul>')
|
514
|
r += htmltext('</div>')
|
515
|
return r.getvalue()
|
516
|
|
517
|
def box_side(self, path):
|
518
|
r = TemplateIO(html=True)
|
519
|
root_url = get_publisher().get_root_url()
|
520
|
|
521
|
if (path == [''] and
|
522
|
'include-tracking-code-form' in get_response().filter.get('keywords', []) and
|
523
|
self.has_anonymous_access_codes()):
|
524
|
r += htmltext('<form id="follow-form" action="%scode/load">') % root_url
|
525
|
r += htmltext('<h3>%s</h3>') % _('Tracking code')
|
526
|
r += htmltext('<input size="12" name="code" placeholder="%s"/>') % _('ex: RPQDFVCD')
|
527
|
r += htmltext('<input type="submit" value="%s"/>') % _('Load')
|
528
|
r += htmltext('</form>')
|
529
|
|
530
|
cats = Category.select(order_by = 'name')
|
531
|
cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side']
|
532
|
Category.sort_by_position(cats)
|
533
|
if cats:
|
534
|
r += htmltext('<div id="side-services">')
|
535
|
r += htmltext('<h3>%s</h3>') % _('Services')
|
536
|
r += htmltext('<ul>')
|
537
|
for cat in cats:
|
538
|
r += htmltext('<li><a href="%s/">%s</a></li>') % (cat.url_name, cat.name)
|
539
|
r += htmltext('</ul>')
|
540
|
r += htmltext('</div>')
|
541
|
|
542
|
v = r.getvalue()
|
543
|
if v:
|
544
|
r = TemplateIO(html=True)
|
545
|
r += htmltext('<div id="sidebox">')
|
546
|
r += v
|
547
|
r += htmltext('</div>')
|
548
|
return r.getvalue()
|
549
|
|
550
|
return None
|
551
|
|
552
|
def has_anonymous_access_codes(self):
|
553
|
return any((x for x in FormDef.select() if x.enable_tracking_codes))
|
554
|
|
555
|
def myspace_snippet(self):
|
556
|
r = TemplateIO(html=True)
|
557
|
r += htmltext('<div id="myspace">')
|
558
|
r += htmltext('<h3>%s</h3>') % _('My Space')
|
559
|
r += htmltext('<ul>')
|
560
|
if get_request().user and not get_request().user.anonymous:
|
561
|
r += htmltext(' <li><a href="myspace/" id="member">%s</a></li>') % _('Access to your personal space')
|
562
|
r += htmltext(' <li><a href="logout" id="logout">%s</a></li>') % _('Logout')
|
563
|
else:
|
564
|
r += htmltext(' <li><a href="register/" id="inscr">%s</a></li>') % _('Registration')
|
565
|
r += htmltext(' <li><a href="login/" id="login">%s</a></li>') % _('Login')
|
566
|
r += htmltext('</ul>')
|
567
|
r += htmltext('</div>')
|
568
|
return r.getvalue()
|
569
|
|
570
|
def page_view(self, key, title, urlname = None):
|
571
|
if not urlname:
|
572
|
urlname = key[3:].replace(str('_'), str('-'))
|
573
|
get_response().breadcrumb.append((urlname, title))
|
574
|
template.html_top(title)
|
575
|
r = TemplateIO(html=True)
|
576
|
r += htmltext('<div class="article">')
|
577
|
r += htmltext(TextsDirectory.get_html_text(key))
|
578
|
r += htmltext('</div>')
|
579
|
return r.getvalue()
|
580
|
|
581
|
def informations_editeur(self):
|
582
|
get_response().filter['bigdiv'] = 'info'
|
583
|
return self.page_view('aq-editor-info', _('Editor Informations'),
|
584
|
urlname = 'informations_editeur')
|
585
|
|
586
|
def accessibility(self):
|
587
|
get_response().filter['bigdiv'] = 'accessibility'
|
588
|
return self.page_view('aq-accessibility', _('Accessibility Statement'))
|
589
|
|
590
|
def contact(self):
|
591
|
get_response().filter['bigdiv'] = 'contact'
|
592
|
return self.page_view('aq-contact', _('Contact'))
|
593
|
|
594
|
def help(self):
|
595
|
get_response().filter['bigdiv'] = 'help'
|
596
|
return self.page_view('aq-help', _('Help'))
|
597
|
|
598
|
|
599
|
from qommon.publisher import get_publisher_class
|
600
|
get_publisher_class().root_directory_class = AlternateRootDirectory
|
601
|
get_publisher_class().after_login_url = 'myspace/'
|
602
|
get_publisher_class().use_sms_feature = True
|
603
|
|
604
|
|
605
|
TextsDirectory.register('aq-editor-info', N_('Editor Informations'))
|
606
|
TextsDirectory.register('aq-accessibility', N_('Accessibility Statement'))
|
607
|
TextsDirectory.register('aq-contact', N_('Contact Information'))
|
608
|
TextsDirectory.register('aq-help', N_('Help'))
|
609
|
TextsDirectory.register('aq-sso-text', N_('Connecting with Identity Provider'),
|
610
|
default = N_('''<h3>Connecting with Identity Provider</h3>
|
611
|
<p>You can also use your identity provider to connect.
|
612
|
</p>'''))
|
613
|
|
614
|
TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg = True)
|