Projet

Général

Profil

Télécharger (49,1 ko) Statistiques
| Branche: | Tag: | Révision:

root / auquotidien / modules / root.py @ e3abbabb

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.misc import get_variadic_url, simplify
6

    
7
import os
8
import re
9
import string
10
import urlparse
11

    
12
try:
13
    import lasso
14
except ImportError:
15
    pass
16

    
17
import wcs
18
import wcs.root
19
import qommon
20
from qommon import _
21
from qommon import get_cfg, get_logger
22
from qommon import template
23
from qommon import errors
24
from qommon.form import *
25
from qommon import logger
26
from wcs.roles import logged_users_role
27

    
28
from qommon import emails
29
from qommon.sms import SMS
30
from wcs.categories import Category
31
from wcs.formdef import FormDef
32
from wcs.data_sources import NamedDataSource
33
from qommon.tokens import Token
34
from qommon.admin.emails import EmailsDirectory
35
from qommon.admin.texts import TextsDirectory
36

    
37
from links import Link
38
from announces import Announce, AnnounceSubscription
39
from myspace import MyspaceDirectory
40
from agenda import AgendaDirectory
41
from events import Event, get_default_event_tags
42
from payments import PublicPaymentDirectory
43
from payments_ui import InvoicesDirectory
44

    
45
import admin
46

    
47
import wcs.forms.root
48
from wcs.workflows import Workflow
49
from wcs.forms.preview import PreviewDirectory
50

    
51
from saml2 import Saml2Directory
52

    
53
OldRootDirectory = wcs.root.RootDirectory
54

    
55
import qommon.ident.password
56
import qommon.ident.idp
57

    
58

    
59
def category_get_homepage_position(self):
60
    if hasattr(self, 'homepage_position') and self.homepage_position:
61
        return self.homepage_position
62
    if self.url_name == 'consultations':
63
        return '2nd'
64
    return '1st'
65
Category.get_homepage_position = category_get_homepage_position
66

    
67
def category_get_limit(self):
68
    if hasattr(self, 'limit') and self.limit is not None:
69
        return self.limit
70
    return 7
71
Category.get_limit = category_get_limit
72

    
73
Category.TEXT_ATTRIBUTES = ['name', 'url_name', 'description', 'homepage_position']
74
Category.INT_ATTRIBUTES = ['position', 'limit']
75

    
76

    
77
class FormsRootDirectory(wcs.forms.root.RootDirectory):
78

    
79
    def _q_index(self, *args):
80
        get_response().filter['is_index'] = True
81
        return wcs.forms.root.RootDirectory._q_index(self, *args)
82

    
83
    def user_forms(self, user_forms):
84
        r = TemplateIO(html=True)
85
        base_url = get_publisher().get_root_url()
86

    
87
        draft = [x for x in user_forms if x.is_draft() and not x.formdef.is_disabled()]
88
        if draft:
89
            r += htmltext('<h4 id="drafts">%s</h4>') % _('My Current Drafts')
90
            r += htmltext('<ul>')
91
            for f in draft:
92
                if f.formdef.category:
93
                    category_url = '%s' % f.formdef.category.url_name
94
                else:
95
                    category_url = '.'
96
                r += htmltext('<li><a href="%s%s/%s/%s">%s</a>, %s') % (base_url,
97
                    category_url,
98
                    f.formdef.url_name, f.id, f.formdef.name,
99
                    misc.localstrftime(f.receipt_time))
100
                r += htmltext(' (<a href="%s%s/%s/%s?remove-draft">%s</a>)') % (base_url,
101
                    category_url,
102
                    f.formdef.url_name, f.id, _('delete'))
103
                r += htmltext('</li>')
104
            r += htmltext('</ul>')
105

    
106
        forms_by_status_name = {}
107
        for f in user_forms:
108
            if f.is_draft():
109
                continue
110
            status = f.get_visible_status()
111
            if status:
112
                status_name = status.name
113
            else:
114
                status_name = None
115
            if status_name in forms_by_status_name:
116
                forms_by_status_name[status_name].append(f)
117
            else:
118
                forms_by_status_name[status_name] = [f]
119
        for status_name in forms_by_status_name:
120
            if status_name:
121
                r += htmltext('<h4>%s</h4>') % _('My forms with status "%s"') % status_name
122
            else:
123
                r += htmltext('<h4>%s</h4>') % _('My forms with an unknown status') % status_name
124
            r += htmltext('<ul>')
125
            forms_by_status_name[status_name].sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
126
            for f in forms_by_status_name[status_name]:
127
                if f.formdef.category_id:
128
                    category_url = f.formdef.category.url_name
129
                else:
130
                    category_url = '.'
131
                r += htmltext('<li><a href="%s%s/%s/%s/">%s</a>, %s</li>') % (
132
                        base_url,
133
                        category_url,
134
                        f.formdef.url_name, f.id, f.formdef.name, 
135
                        misc.localstrftime(f.receipt_time))
136
            r += htmltext('</ul>')
137
        return r.getvalue()
138

    
139

    
140
class AnnounceDirectory(Directory):
141
    _q_exports = ['', 'edit', 'delete', 'email']
142

    
143
    def __init__(self, announce):
144
        self.announce = announce
145

    
146
    def _q_index(self):
147
        template.html_top(_('Announces to citizens'))
148
        r = TemplateIO(html=True)
149

    
150
        if self.announce.publication_time:
151
            date_heading = '%s - ' % time.strftime(misc.date_format(), self.announce.publication_time)
152
        else:
153
            date_heading = ''
154

    
155
        r += htmltext('<h3>%s%s</h3>') % (date_heading, self.announce.title)
156

    
157
        r += htmltext('<p>')
158
        r += self.announce.text
159
        r += htmltext('</p>')
160

    
161
        r += htmltext('<p>')
162
        r += htmltext('<a href="../">%s</a>') % _('Back')
163
        r += htmltext('</p>')
164
        return r.getvalue()
165

    
166

    
167
class AnnouncesDirectory(Directory):
168
    _q_exports = ['', 'subscribe', 'email', 'atom', 'sms', 'emailconfirm',
169
            'email_unsubscribe', 'sms_unsubscribe', 'smsconfirm', 'rawlist']
170

    
171
    def _q_traverse(self, path):
172
        get_response().breadcrumb.append(('announces/', _('Announces')))
173
        return Directory._q_traverse(self, path)
174

    
175
    def _q_index(self):
176
        template.html_top(_('Announces to citizens'))
177
        r = TemplateIO(html=True)
178
        r += self.announces_list()
179
        r += htmltext('<ul id="announces-links">')
180
        r += htmltext('<li><a href="subscribe">%s</a></li>') % _('Receiving those Announces')
181
        r += htmltext('</ul>')
182
        return r.getvalue()
183

    
184
    def _get_announce_subscription(self):
185
        """ """
186
        sub = None
187
        if get_request().user:
188
            subs = AnnounceSubscription.select(lambda x: x.user_id == get_request().user.id)
189
            if subs:
190
                sub = subs[0]
191
        return sub
192

    
193
    def rawlist(self):
194
        get_response().filter = None
195
        return self.announces_list()
196

    
197
    def announces_list(self):
198
        announces = Announce.get_published_announces()
199
        if not announces:
200
            raise errors.TraversalError()
201

    
202
        # XXX: will need pagination someday
203
        r = TemplateIO(html=True)
204
        for item in announces:
205
            r += htmltext('<div class="announce-item">\n')
206
            r += htmltext('<h4>')
207
            if item.publication_time:
208
                r += time.strftime(misc.date_format(), item.publication_time)
209
                r += ' - '
210
            r += item.title
211
            r += htmltext('</h4>\n')
212
            r += htmltext('<p>\n')
213
            r += item.text
214
            r += htmltext('\n</p>\n')
215
            r += htmltext('</div>\n')
216
        return r.getvalue()
217

    
218

    
219
    def sms(self):
220
        sms_mode = get_cfg('sms', {}).get('mode', 'none')
221

    
222
        if sms_mode == 'none':
223
            raise errors.TraversalError()
224

    
225
        get_response().breadcrumb.append(('sms', _('SMS')))
226
        template.html_top(_('Receiving announces by SMS'))
227
        r = TemplateIO(html=True)
228

    
229
        if sms_mode == 'demo':
230
            r += TextsDirectory.get_html_text('aq-sms-demo')
231
        else:
232
            announces_cfg = get_cfg('announces',{})
233
            mobile_mask = announces_cfg.get('mobile_mask')
234
            if mobile_mask:
235
                mobile_mask = ' (' + mobile_mask + ')'
236
            else:
237
                mobile_mask = ''
238
            form = Form(enctype='multipart/form-data')
239
            form.add(StringWidget, 'mobile', title = _('Mobile number %s') % mobile_mask, size=12, required=True)
240
            form.add_submit('submit', _('Subscribe'))
241
            form.add_submit('cancel', _('Cancel'))
242

    
243
            if form.get_submit() == 'cancel':
244
                return redirect('subscribe')
245

    
246
            if form.is_submitted() and not form.has_errors():
247
                s = self.sms_submit(form)
248
                if s == False:
249
                    r += form.render()
250
                else:
251
                    return redirect("smsconfirm")
252
            else:
253
                r += form.render()
254
        return r.getvalue()
255

    
256
    def sms_submit(self, form):
257
        mobile = form.get_widget("mobile").parse()
258
        # clean the string, remove any extra character
259
        mobile = re.sub('[^0-9+]','',mobile)
260
        # if a mask was set, validate
261
        announces_cfg = get_cfg('announces',{})
262
        mobile_mask = announces_cfg.get('mobile_mask')
263
        if mobile_mask:
264
            mobile_regexp = re.sub('X','[0-9]', mobile_mask) + '$'
265
            if not re.match(mobile_regexp, mobile):
266
                form.set_error("mobile", _("Phone number invalid ! It must match ") + mobile_mask)
267
                return False
268
        if mobile.startswith('00'):
269
            mobile = '+' + mobile[2:]
270
        else:
271
            # Default to france international prefix
272
            if not mobile.startswith('+'):
273
                mobile = re.sub("^0", "+33", mobile)
274
        sub = self._get_announce_subscription()
275
        if not sub:
276
            sub = AnnounceSubscription()
277
        if get_request().user:
278
            sub.user_id = get_request().user.id
279

    
280
        if mobile:
281
            sub.sms = mobile
282

    
283
        if not get_request().user:
284
            sub.enabled = False
285

    
286
        sub.store()
287

    
288
        # Asking sms confirmation
289
        token = Token(3 * 86400, 4, string.digits)
290
        token.type = 'announces-subscription-confirmation'
291
        token.subscription_id = sub.id
292
        token.store()
293

    
294
        message = _("Confirmation code : %s") % str(token.id)
295
        sms_cfg = get_cfg('sms', {})
296
        sender = sms_cfg.get('sender', 'AuQuotidien')[:11]
297
        mode = sms_cfg.get('mode', 'none')
298
        sms = SMS.get_sms_class(mode)
299
        try:
300
            sms.send(sender, [mobile], message)
301
        except errors.SMSError, e:
302
            get_logger().error(e)
303
            form.set_error("mobile", _("Send SMS confirmation failed"))
304
            sub.remove("sms")
305
            return False
306

    
307
    def smsconfirm(self):
308
        template.html_top(_('Receiving announces by SMS confirmation'))
309
        r = TemplateIO(html=True)
310
        r += htmltext("<p>%s</p>") % _("You will receive a confirmation code by SMS.")
311
        form = Form(enctype='multipart/form-data')
312
        form.add(StringWidget, 'code', title = _('Confirmation code (4 characters)'), size=12, required=True)
313
        form.add_submit('submit', _('Subscribe'))
314
        form.add_submit('cancel', _('Cancel'))
315

    
316
        if form.get_submit() == 'cancel':
317
            return redirect('..')
318

    
319
        if form.is_submitted() and not form.has_errors():
320
            token = None
321
            id = form.get_widget("code").parse()
322
            try:
323
                token = Token.get(id)
324
            except KeyError:
325
                form.set_error("code",  _('Invalid confirmation code.'))
326
            else:
327
                if token.type != 'announces-subscription-confirmation':
328
                    form.set_error("code",  _('Invalid confirmation code.'))
329
                else:
330
                    sub = AnnounceSubscription.get(token.subscription_id)
331
                    token.remove_self()
332
                    sub.enabled_sms = True
333
                    sub.store()
334
                    return redirect('.')
335
            r += form.render()
336
        else:
337
            r += form.render()
338

    
339
        return r.getvalue()
340

    
341
    def sms_unsubscribe(self):
342
        sub = self._get_announce_subscription()
343

    
344
        form = Form(enctype='multipart/form-data')
345
        if not sub:
346
            return redirect('..')
347

    
348
        form.add_submit('submit', _('Unsubscribe'))
349
        form.add_submit('cancel', _('Cancel'))
350

    
351
        if form.get_submit() == 'cancel':
352
            return redirect('..')
353

    
354
        get_response().breadcrumb.append(('sms', _('SMS Unsubscription')))
355
        template.html_top()
356
        r = TemplateIO(html=True)
357

    
358
        if form.is_submitted() and not form.has_errors():
359
            if sub:
360
                sub.remove("sms")
361

    
362
            root_url = get_publisher().get_root_url()
363
            r += htmltext('<p>')
364
            r += _('You have been unsubscribed from announces')
365
            r += htmltext('</p>')
366
            if not get_response().iframe_mode:
367
                r += htmltext('<a href="%s">%s</a>') % (root_url, _('Back Home'))
368
        else:
369
            r += htmltext('<p>')
370
            r += _('Do you want to stop receiving announces by sms ?')
371
            r += htmltext('</p>')
372
            r += form.render()
373

    
374
        return r.getvalue()
375

    
376

    
377
    def subscribe(self):
378
        get_response().breadcrumb.append(('subscribe', _('Subscription')))
379
        template.html_top(_('Receiving Announces'))
380
        r = TemplateIO(html=True)
381

    
382
        r += TextsDirectory.get_html_text('aq-announces-subscription')
383

    
384
        sub = self._get_announce_subscription()
385

    
386
        r += htmltext('<ul id="announce-modes">')
387
        if sub and sub.email:
388
            r += htmltext(' <li>')
389
            r += htmltext('<span id="par_mail">%s</span>') % _('Email (currently subscribed)')
390
            r += htmltext(' <a href="email_unsubscribe" rel="popup">%s</a></li>') % _('Unsubscribe')
391
        else:
392
            r += htmltext(' <li><a href="email" id="par_mail" rel="popup">%s</a></li>') % _('Email')
393
        if sub and sub.sms:
394
            r += htmltext(' <li>')
395
            if sub.enabled_sms:
396
                r += htmltext('<span id="par_sms">%s</span>') % _('SMS %s (currently subscribed)') % sub.sms
397
            else:
398
                r += htmltext('<span id="par_sms">%s</span>') % _('SMS %s (currently not confirmed)') % sub.sms
399
                r += htmltext(' <a href="smsconfirm" rel="popup">%s</a> ') % _('Confirmation')
400
            r += htmltext(' <a href="sms_unsubscribe" rel="popup">%s</a></li>') % _('Unsubscribe')
401
        elif get_cfg('sms', {}).get('mode', 'none') != 'none':
402
            r += htmltext(' <li><a href="sms" id="par_sms">%s</a></li>') % _('SMS')
403
        r += htmltext(' <li><a class="feed-link" href="atom" id="par_rss">%s</a>') % _('Feed')
404
        r += htmltext('</ul>')
405
        return r.getvalue()
406

    
407
    def email(self):
408
        get_response().breadcrumb.append(('email', _('Email Subscription')))
409
        template.html_top(_('Receiving Announces by email'))
410
        r = TemplateIO(html=True)
411

    
412
        form = Form(enctype='multipart/form-data')
413
        if get_request().user:
414
            if get_request().user.email:
415
                r += htmltext('<p>')
416
                r += _('You are logged in and your email is %s, ok to subscribe ?') % \
417
                        get_request().user.email
418
                r += htmltext('</p>')
419
                form.add_submit('submit', _('Subscribe'))
420
            else:
421
                r += htmltext('<p>')
422
                r += _("You are logged in but there is no email address in your profile.")
423
                r += htmltext('</p>')
424
                form.add(EmailWidget, 'email', title = _('Email'), required = True)
425
                form.add_submit('submit', _('Subscribe'))
426
                form.add_submit('submit-remember', _('Subscribe and add this email to my profile'))
427
        else:
428
            r += htmltext('<p>')
429
            r += _('FIXME will only be used for this purpose etc.')
430
            r += htmltext('</p>')
431
            form.add(EmailWidget, 'email', title = _('Email'), required = True)
432
            form.add_submit('submit', _('Subscribe'))
433

    
434
        form.add_submit('cancel', _('Cancel'))
435

    
436
        if form.get_submit() == 'cancel':
437
            return redirect('subscribe')
438

    
439
        if form.is_submitted() and not form.has_errors():
440
            s = self.email_submit(form)
441
            if s is not False:
442
                return s
443
        else:
444
            r += form.render()
445

    
446
        return r.getvalue()
447

    
448
    def email_submit(self, form):
449
        sub = self._get_announce_subscription()
450
        if not sub:
451
            sub = AnnounceSubscription()
452

    
453
        if get_request().user:
454
            sub.user_id = get_request().user.id
455

    
456
        if form.get_widget('email'):
457
            sub.email = form.get_widget('email').parse()
458
        elif get_request().user.email:
459
            sub.email = get_request().user.email
460

    
461
        if not get_request().user:
462
            sub.enabled = False
463

    
464
        sub.store()
465

    
466
        if get_request().user:
467
            r = TemplateIO(html=True)
468
            root_url = get_publisher().get_root_url()
469
            r += htmltext('<p>')
470
            r += _('You have been subscribed to the announces.')
471
            r += htmltext('</p>')
472
            if not get_response().iframe_mode:
473
                r += htmltext('<a href="%s">%s</a>') % (root_url, _('Back Home'))
474
            return r.getvalue()
475

    
476
        # asking email confirmation before subscribing someone
477
        token = Token(3 * 86400)
478
        token.type = 'announces-subscription-confirmation'
479
        token.subscription_id = sub.id
480
        token.store()
481
        data = {
482
            'confirm_url': get_request().get_url() + 'confirm?t=%s&a=cfm' % token.id,
483
            'cancel_url': get_request().get_url() + 'confirm?t=%s&a=cxl' % token.id,
484
            'time': misc.localstrftime(time.localtime(token.expiration)),
485
        }
486

    
487
        emails.custom_ezt_email('announces-subscription-confirmation',
488
                data, sub.email, exclude_current_user = False)
489

    
490
        r = TemplateIO(html=True)
491
        root_url = get_publisher().get_root_url()
492
        r += htmltext('<p>')
493
        r += _('You have been sent an email for confirmation')
494
        r += htmltext('</p>')
495
        if not get_response().iframe_mode:
496
            r += htmltext('<a href="%s">%s</a>') % (root_url, _('Back Home'))
497
        return r.getvalue()
498

    
499
    def emailconfirm(self):
500
        tokenv = get_request().form.get('t')
501
        action = get_request().form.get('a')
502

    
503
        root_url = get_publisher().get_root_url()
504

    
505
        try:
506
            token = Token.get(tokenv)
507
        except KeyError:
508
            return template.error_page(
509
                    _('The token you submitted does not exist, has expired, or has been cancelled.'),
510
                    continue_to = (root_url, _('home page')))
511

    
512
        if token.type != 'announces-subscription-confirmation':
513
            return template.error_page(
514
                    _('The token you submitted is not appropriate for the requested task.'),
515
                    continue_to = (root_url, _('home page')))
516

    
517
        sub = AnnounceSubscription.get(token.subscription_id)
518

    
519
        if action == 'cxl':
520
            r = TemplateIO(html=True)
521
            root_url = get_publisher().get_root_url()
522
            template.html_top(_('Email Subscription'))
523
            r += htmltext('<h1>%s</h1>') % _('Request Cancelled')
524
            r += htmltext('<p>%s</p>') % _('The request for subscription has been cancelled.')
525
            r += htmltext('<p>')
526
            r += htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
527
            r += htmltext('</p>')
528
            token.remove_self()
529
            sub.remove_self()
530
            return r.getvalue()
531

    
532
        if action == 'cfm':
533
            token.remove_self()
534
            sub.enabled = True
535
            sub.store()
536
            r = TemplateIO(html=True)
537
            root_url = get_publisher().get_root_url()
538
            template.html_top(_('Email Subscription'))
539
            r += htmltext('<h1>%s</h1>') % _('Subscription Confirmation')
540
            r += htmltext('<p>%s</p>') % _('Your subscription to announces is now effective.')
541
            r += htmltext('<p>')
542
            r += htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
543
            r += htmltext('</p>')
544
            return r.getvalue()
545

    
546
    def atom(self):
547
        response = get_response()
548
        response.set_content_type('application/atom+xml')
549

    
550
        from pyatom import pyatom
551
        xmldoc = pyatom.XMLDoc()
552
        feed = pyatom.Feed()
553
        xmldoc.root_element = feed
554
        feed.title = get_cfg('misc', {}).get('sitename') or 'Publik'
555
        feed.id = get_request().get_url()
556

    
557
        author_email = get_cfg('emails', {}).get('reply_to')
558
        if not author_email:
559
            author_email = get_cfg('emails', {}).get('from')
560
        if author_email:
561
            feed.authors.append(pyatom.Author(author_email))
562

    
563
        announces = Announce.get_published_announces()
564

    
565
        if announces and announces[0].modification_time:
566
            feed.updated = misc.format_time(announces[0].modification_time,
567
                        '%(year)s-%(month)02d-%(day)02dT%(hour)02d:%(minute)02d:%(second)02dZ',
568
                        gmtime = True)
569
        feed.links.append(pyatom.Link(get_request().get_url(1) + '/'))
570

    
571
        for item in announces:
572
            entry = item.get_atom_entry()
573
            if entry:
574
                feed.entries.append(entry)
575

    
576
        return str(feed)
577

    
578
    def email_unsubscribe(self):
579
        sub = self._get_announce_subscription()
580

    
581
        form = Form(enctype='multipart/form-data')
582
        if not sub:
583
            form.add(EmailWidget, 'email', title = _('Email'), required = True)
584

    
585
        form.add_submit('submit', _('Unsubscribe'))
586
        form.add_submit('cancel', _('Cancel'))
587

    
588
        if form.get_submit() == 'cancel':
589
            return redirect('..')
590

    
591
        get_response().breadcrumb.append(('email', _('Email Unsubscription')))
592
        template.html_top()
593
        r = TemplateIO(html=True)
594

    
595
        if form.is_submitted() and not form.has_errors():
596
            if sub:
597
                sub.remove("email")
598
            else:
599
                email = form.get_widget('email').parse()
600
                for s in AnnounceSubscription.select():
601
                    if s.email == email:
602
                        s.remove("email")
603

    
604
            root_url = get_publisher().get_root_url()
605
            r += htmltext('<p>')
606
            r += _('You have been unsubscribed from announces')
607
            r += htmltext('</p>')
608
            if not get_response().iframe_mode:
609
                r += htmltext('<a href="%s">%s</a>') % (root_url, _('Back Home'))
610

    
611
        else:
612
            r += htmltext('<p>')
613
            r += _('Do you want to stop receiving announces by email?')
614
            r += htmltext('</p>')
615
            r += form.render()
616

    
617
        return r.getvalue()
618

    
619
    def _q_lookup(self, component):
620
        try:
621
            announce = Announce.get(component)
622
        except KeyError:
623
            raise errors.TraversalError()
624

    
625
        if announce.hidden:
626
            raise errors.TraversalError()
627

    
628
        get_response().breadcrumb.append((str(announce.id), announce.title))
629
        return AnnounceDirectory(announce)
630

    
631
OldRegisterDirectory = wcs.root.RegisterDirectory
632

    
633
class AlternateRegisterDirectory(OldRegisterDirectory):
634
    def _q_traverse(self, path):
635
        get_response().filter['bigdiv'] = 'new_member'
636
        return OldRegisterDirectory._q_traverse(self, path)
637

    
638
    def _q_index(self):
639
        get_logger().info('register')
640
        ident_methods = get_cfg('identification', {}).get('methods', [])
641

    
642
        if len(ident_methods) == 0:
643
            idps = get_cfg('idp', {})
644
            if len(idps) == 0:
645
                return template.error_page(_('Authentication subsystem is not yet configured.'))
646
            ident_methods = ['idp'] # fallback to old behaviour; saml.
647

    
648
        if len(ident_methods) == 1:
649
            method = ident_methods[0]
650
        else:
651
            method = 'password'
652

    
653
        return qommon.ident.register(method)
654

    
655
OldLoginDirectory = wcs.root.LoginDirectory
656

    
657
class AlternateLoginDirectory(OldLoginDirectory):
658
    def _q_traverse(self, path):
659
        get_response().filter['bigdiv'] = 'member'
660
        return OldLoginDirectory._q_traverse(self, path)
661

    
662
    def _q_index(self):
663
        get_logger().info('login')
664
        ident_methods = get_cfg('identification', {}).get('methods', [])
665

    
666
        if get_request().form.get('ReturnUrl'):
667
            get_request().form['next'] = get_request().form.pop('ReturnUrl')
668

    
669
        if 'IsPassive' in get_request().form and 'idp' in ident_methods:
670
            # if isPassive is given in query parameters, we restrict ourselves
671
            # to saml login.
672
            ident_methods = ['idp']
673

    
674
        if len(ident_methods) > 1 and 'idp' in ident_methods:
675
            # if there is more than one identification method, and there is a
676
            # possibility of SSO, if we got there as a consequence of an access
677
            # unauthorized url on admin/ or backoffice/, then idp auth method
678
            # is chosen forcefully.
679
            after_url = get_request().form.get('next')
680
            if after_url:
681
                root_url = get_publisher().get_root_url()
682
                after_path = urlparse.urlparse(after_url)[2]
683
                after_path = after_path[len(root_url):]
684
                if after_path.startswith(str('admin')) or \
685
                        after_path.startswith(str('backoffice')):
686
                    ident_methods = ['idp']
687

    
688
        # don't display authentication system choice
689
        if len(ident_methods) == 1:
690
            method = ident_methods[0]
691
            try:
692
                return qommon.ident.login(method)
693
            except KeyError:
694
                get_logger().error('failed to login with method %s' % method)
695
                return errors.TraversalError()
696

    
697
        if sorted(ident_methods) == ['idp', 'password']:
698
            r = TemplateIO(html=True)
699
            get_response().breadcrumb.append(('login', _('Login')))
700
            identities_cfg = get_cfg('identities', {})
701
            form = Form(enctype = 'multipart/form-data', id = 'login-form', use_tokens = False)
702
            if identities_cfg.get('email-as-username', False):
703
                form.add(StringWidget, 'username', title = _('Email'), size=25, required=True)
704
            else:
705
                form.add(StringWidget, 'username', title = _('Username'), size=25, required=True)
706
            form.add(PasswordWidget, 'password', title = _('Password'), size=25, required=True)
707
            form.add_submit('submit', _('Connect'))
708
            if form.is_submitted() and not form.has_errors():
709
                tmp = qommon.ident.password.MethodDirectory().login_submit(form)
710
                if not form.has_errors():
711
                    return tmp
712

    
713
            r += htmltext('<div id="login-password">')
714
            r += get_session().display_message()
715
            r += form.render()
716

    
717
            base_url = get_publisher().get_root_url()
718
            r += htmltext('<p><a href="%sident/password/forgotten">%s</a></p>') % (
719
                    base_url, _('Forgotten password ?'))
720

    
721
            r += htmltext('</div>')
722

    
723
            # XXX: this part only supports a single IdP
724
            r += htmltext('<div id="login-sso">')
725
            r += TextsDirectory.get_html_text('aq-sso-text')
726
            form = Form(enctype='multipart/form-data',
727
                    action = '%sident/idp/login' % base_url)
728
            form.add_hidden('method', 'idp')
729
            for kidp, idp in get_cfg('idp', {}).items():
730
                p = lasso.Provider(lasso.PROVIDER_ROLE_IDP,
731
                        misc.get_abs_path(idp['metadata']),
732
                        misc.get_abs_path(idp.get('publickey')), None)
733
                form.add_hidden('idp', p.providerId)
734
                break
735
            form.add_submit('submit', _('Connect'))
736

    
737
            r += form.render()
738
            r += htmltext('</div>')
739

    
740
            get_request().environ['REQUEST_METHOD'] = 'GET'
741

    
742
            r += htmltext("""<script type="text/javascript">
743
              document.getElementById('login-form')['username'].focus();
744
            </script>""")
745
            return r.getvalue()
746
        else:
747
            return OldLoginDirectory._q_index(self)
748

    
749

    
750
OldIdentDirectory = wcs.root.IdentDirectory
751
class AlternateIdentDirectory(OldIdentDirectory):
752
    def _q_traverse(self, path):
753
        get_response().filter['bigdiv'] = 'member'
754
        return OldIdentDirectory._q_traverse(self, path)
755

    
756

    
757
class AlternatePreviewDirectory(PreviewDirectory):
758
    def _q_traverse(self, path):
759
        get_response().filter['bigdiv'] = 'rub_service'
760
        return super(AlternatePreviewDirectory, self)._q_traverse(path)
761

    
762

    
763
class AlternateRootDirectory(OldRootDirectory):
764
    _q_exports = ['', 'admin', 'backoffice', 'forms', 'login', 'logout',
765
            'saml', 'register', 'ident', 'afterjobs',
766
            ('informations-editeur', 'informations_editeur'),
767
            ('announces', 'announces_dir'),
768
            'accessibility', 'contact', 'help',
769
            'myspace', 'services', 'agenda', 'categories', 'user',
770
            ('tmp-upload', 'tmp_upload'), 'json', '__version__',
771
            'themes', 'pages', 'payment', 'invoices', 'roles',
772
            'api', 'code', 'fargo', 'tryauth', 'auth', 'preview',
773
            ('reload-top', 'reload_top'), 'static',
774
            ('i18n.js', 'i18n_js')]
775

    
776
    admin = admin.AdminRootDirectory()
777
    announces_dir = AnnouncesDirectory()
778
    register = AlternateRegisterDirectory()
779
    login = AlternateLoginDirectory()
780
    ident = AlternateIdentDirectory()
781
    myspace = MyspaceDirectory()
782
    agenda = AgendaDirectory()
783
    saml = Saml2Directory()
784
    payment = PublicPaymentDirectory()
785
    invoices = InvoicesDirectory()
786
    code = wcs.forms.root.TrackingCodesDirectory()
787
    preview = AlternatePreviewDirectory()
788

    
789
    def get_substitution_variables(self):
790
        d = {}
791
        def print_links(fd):
792
            fd.write(str(self.links()))
793
        d['links'] = print_links
794
        return d
795

    
796
    def _q_traverse(self, path):
797
        self.feed_substitution_parts()
798

    
799
        # set app_label to Publik if none was specified (this is used in
800
        # backoffice header top line)
801
        if not get_publisher().get_site_option('app_label'):
802
            if not get_publisher().site_options.has_section('options'):
803
                get_publisher().site_options.add_section('options')
804
            get_publisher().site_options.set('options', 'app_label', 'Publik')
805

    
806
        response = get_response()
807
        if not hasattr(response, 'filter'):
808
            response.filter = {}
809

    
810
        response.filter['auquotidien'] = True
811
        if not path or path[0] not in ('api', 'backoffice'):
812
            # api & backoffice have no use for a side box
813
            response.filter['gauche'] = self.box_side(path)
814
            response.filter['keywords'] = template.get_current_theme().get('keywords')
815
        get_publisher().substitutions.feed(self)
816

    
817
        response.breadcrumb = [ ('', _('Home')) ]
818

    
819
        if not self.admin:
820
            self.admin = get_publisher().admin_directory_class()
821

    
822
        if not self.backoffice:
823
            self.backoffice = get_publisher().backoffice_directory_class()
824

    
825
        try:
826
            return Directory._q_traverse(self, path)
827
        except errors.TraversalError, e:
828
            try:
829
                f = FormDef.get_by_urlname(path[0])
830
            except KeyError:
831
                pass
832
            else:
833
                base_url = get_publisher().get_root_url()
834

    
835
                uri_rest = get_request().environ.get('REQUEST_URI')
836
                if not uri_rest:
837
                    # REQUEST_URI doesn't exist when using internal HTTP server
838
                    # (--http)
839
                    uri_rest = get_request().get_path()
840
                    if get_request().get_query():
841
                        uri_rest += '?' + get_request().get_query()
842
                if uri_rest.startswith(base_url):
843
                    uri_rest = uri_rest[len(base_url):]
844
                if f.category:
845
                    return redirect('%s%s/%s' % (base_url, f.category.url_name, uri_rest))
846

    
847
            raise e
848

    
849

    
850
    def _q_lookup(self, component):
851
        # is this a category ?
852
        try:
853
            category = Category.get_by_urlname(component)
854
        except KeyError:
855
            pass
856
        else:
857
            return FormsRootDirectory(category)
858

    
859
        # is this a formdef ?
860
        try:
861
            formdef = FormDef.get_by_urlname(component)
862
        except KeyError:
863
            pass
864
        else:
865
            # if there's no category, or the request is a POST, directly call
866
            # into FormsRootDirectory.
867
            if formdef.category_id is None or get_request().get_method() == 'POST':
868
                get_response().filter['bigdiv'] = 'rub_service'
869
                return FormsRootDirectory()._q_lookup(component)
870

    
871
            # if there is category, let it fall back to raise TraversalError,
872
            # it will get caught in _q_traverse that will redirect it to an
873
            # URL embedding the category
874

    
875
        return None
876

    
877
    def json(self):
878
        return FormsRootDirectory().json()
879

    
880
    def categories(self):
881
        return FormsRootDirectory().categories()
882

    
883
    def _q_index(self):
884
        if get_request().is_json():
885
            return FormsRootDirectory().json()
886

    
887
        root_url = get_publisher().get_root_url()
888
        if get_request().user and get_request().user.anonymous and get_request().user.lasso_dump:
889
            return redirect('%smyspace/new' % root_url)
890

    
891
        redirect_url = get_cfg('misc', {}).get('homepage-redirect-url')
892
        if redirect_url:
893
            return redirect(misc.get_variadic_url(redirect_url,
894
                get_publisher().substitutions.get_context_variables()))
895

    
896
        if get_response().iframe_mode:
897
            # never display home page in an iframe
898
            return redirect('%sservices' % root_url)
899

    
900
        template.html_top()
901
        r = TemplateIO(html=True)
902
        get_response().filter['is_index'] = True
903

    
904
        if not 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
905
            t = TextsDirectory.get_html_text('aq-home-page')
906
            if not t:
907
                if get_request().user:
908
                    t = TextsDirectory.get_html_text('welcome-logged')
909
                else:
910
                    t = TextsDirectory.get_html_text('welcome-unlogged')
911
            if t:
912
                r += htmltext('<div id="home-page-intro">')
913
                r += t
914
                r += htmltext('</div>')
915

    
916
        r += htmltext('<div id="centre">')
917
        r += self.box_services(position='1st')
918
        r += htmltext('</div>')
919
        r += htmltext('<div id="droite">')
920
        r += self.myspace_snippet()
921
        r += self.box_services(position='2nd')
922
        r += self.consultations()
923
        r += self.announces()
924
        r += htmltext('</div>')
925

    
926
        user = get_request().user
927
        if user and user.can_go_in_backoffice():
928
            get_response().filter['backoffice'] = True
929

    
930
        return r.getvalue()
931

    
932
    def services(self):
933
        template.html_top()
934
        get_response().filter['bigdiv'] = 'rub_service'
935
        return self.box_services(level = 2)
936

    
937
    def box_services(self, level=3, position=None):
938
        ## Services
939
        if get_request().user and get_request().user.roles:
940
            accepted_roles = get_request().user.roles
941
        else:
942
            accepted_roles = []
943

    
944
        cats = Category.select(order_by = 'name')
945
        cats = [x for x in cats if x.url_name != 'consultations']
946
        Category.sort_by_position(cats)
947

    
948
        all_formdefs = FormDef.select(lambda x: not x.is_disabled() or x.disabled_redirection,
949
                order_by = 'name')
950
        if get_response().page_template_key == 'mobile':
951
            # if we are in 'mobile' mode, and some formdefs have a 'mobile'
952
            # keyword, we limit the display to those
953
            if any((x for x in all_formdefs if x.keywords and 'mobile' in x.keywords)):
954
                all_formdefs = [x for x in all_formdefs if x.keywords and 'mobile' in x.keywords]
955

    
956
        if position:
957
            t = self.display_list_of_formdefs(
958
                            [x for x in cats if x.get_homepage_position() == position],
959
                            all_formdefs, accepted_roles)
960
        else:
961
            t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles)
962

    
963
        if not t:
964
            return
965

    
966
        r = TemplateIO(html=True)
967

    
968
        if position == '2nd':
969
            r += htmltext('<div id="services-2nd">')
970
        else:
971
            r += htmltext('<div id="services">')
972
        if level == 2:
973
            r += htmltext('<h2>%s</h2>') % _('Services')
974
        else:
975
            r += htmltext('<h3>%s</h3>') % _('Services')
976

    
977
        if get_response().iframe_mode:
978
            if get_request().user:
979
                message = TextsDirectory.get_html_text('welcome-logged')
980
            else:
981
                message = TextsDirectory.get_html_text('welcome-unlogged')
982

    
983
            if message:
984
                r += htmltext('<div id="welcome-message">')
985
                r += message
986
                r += htmltext('</div>')
987
        elif 'auquotidien-welcome-in-services' in get_response().filter.get('keywords', []):
988
            homepage_text = TextsDirectory.get_html_text('aq-home-page')
989
            if homepage_text:
990
                r += htmltext('<div id="home-page-intro">')
991
                r += homepage_text
992
                r += htmltext('</div>')
993

    
994
        r += htmltext('<ul>')
995
        r += t
996
        r += htmltext('</ul>')
997

    
998
        r += htmltext('</div>')
999
        return r.getvalue()
1000

    
1001
    def display_list_of_formdefs(self, cats, all_formdefs, accepted_roles):
1002
        r = TemplateIO(html=True)
1003
        for category in cats:
1004
            if category.url_name == 'consultations':
1005
                self.consultations_category = category
1006
                continue
1007
            formdefs = [x for x in all_formdefs if str(x.category_id) == str(category.id)]
1008
            formdefs_advertise = []
1009

    
1010
            for formdef in formdefs[:]:
1011
                if formdef.is_disabled(): # is a redirection
1012
                    continue
1013
                if not formdef.roles:
1014
                    continue
1015
                if not get_request().user:
1016
                    if formdef.always_advertise:
1017
                        formdefs_advertise.append(formdef)
1018
                    formdefs.remove(formdef)
1019
                    continue
1020
                if logged_users_role().id in formdef.roles:
1021
                    continue
1022
                for q in accepted_roles:
1023
                    if q in formdef.roles:
1024
                        break
1025
                else:
1026
                    if formdef.always_advertise:
1027
                        formdefs_advertise.append(formdef)
1028
                    formdefs.remove(formdef)
1029

    
1030
            if not formdefs and not formdefs_advertise:
1031
                continue
1032

    
1033
            keywords = {}
1034
            for formdef in formdefs:
1035
                for keyword in formdef.keywords_list:
1036
                    keywords[keyword] = True
1037

    
1038
            r += htmltext('<li id="category-%s" data-keywords="%s">') % (
1039
                    category.url_name, ' '.join(keywords))
1040
            r += htmltext('<strong>')
1041
            r += htmltext('<a href="%s/">') % category.url_name
1042
            r += category.name
1043
            r += htmltext('</a></strong>\n')
1044
            r += category.get_description_html_text()
1045
            r += htmltext('<ul>')
1046
            limit = category.get_limit()
1047
            for formdef in formdefs[:limit]:
1048
                r += htmltext('<li data-keywords="%s">') % ' '.join(formdef.keywords_list)
1049
                classes = []
1050
                if formdef.is_disabled() and formdef.disabled_redirection:
1051
                    classes.append('redirection')
1052
                r += htmltext('<a class="%s" href="%s/%s/">%s</a>') % (
1053
                        ' '.join(classes), category.url_name, formdef.url_name, formdef.name)
1054
                r += htmltext('</li>\n')
1055
            if len(formdefs) < limit:
1056
                for formdef in formdefs_advertise[:limit-len(formdefs)]:
1057
                    r += htmltext('<li class="required-authentication">')
1058
                    r += htmltext('<a href="%s/%s/">%s</a>') % (category.url_name, formdef.url_name, formdef.name)
1059
                    r += htmltext('<span> (%s)</span>') % _('authentication required')
1060
                    r += htmltext('</li>\n')
1061
            if (len(formdefs)+len(formdefs_advertise)) > limit:
1062
                r += htmltext('<li class="all-forms"><a href="%s/" title="%s">%s</a></li>') % (category.url_name,
1063
                        _('Access to all forms of the "%s" category') % category.name,
1064
                        _('Access to all forms in this category'))
1065
            r += htmltext('</ul>')
1066
            r += htmltext('</li>\n')
1067

    
1068
        return r.getvalue()
1069

    
1070
    def consultations(self):
1071
        cats = [x for x in Category.select() if x.url_name == 'consultations']
1072
        if not cats:
1073
            return
1074
        consultations_category = cats[0]
1075
        formdefs = FormDef.select(lambda x: (
1076
                    str(x.category_id) == str(consultations_category.id) and
1077
                        (not x.is_disabled() or x.disabled_redirection)),
1078
                    order_by = 'name')
1079
        if not formdefs:
1080
            return
1081
        ## Consultations
1082
        r = TemplateIO(html=True)
1083
        r += htmltext('<div id="consultations">')
1084
        r += htmltext('<h3>%s</h3>') % _('Consultations')
1085
        r += consultations_category.get_description_html_text()
1086
        r += htmltext('<ul>')
1087
        for formdef in formdefs:
1088
            r += htmltext('<li>')
1089
            r += htmltext('<a href="%s/%s/">%s</a>') % (consultations_category.url_name,
1090
                formdef.url_name, formdef.name)
1091
            r += htmltext('</li>')
1092
        r += htmltext('</ul>')
1093
        r += htmltext('</div>')
1094
        return r.getvalue()
1095

    
1096
    def box_side(self, path):
1097
        r = TemplateIO(html=True)
1098
        root_url = get_publisher().get_root_url()
1099

    
1100
        if self.has_anonymous_access_codes() and path == [''] and (
1101
                'include-tracking-code-form' in get_response().filter.get('keywords', [])):
1102
            r += htmltext('<form id="follow-form" action="%scode/load">') % root_url
1103
            r += htmltext('<h3>%s</h3>') % _('Tracking code')
1104
            r += htmltext('<input size="12" name="code" placeholder="%s"/>') % _('ex: RPQDFVCD')
1105
            r += htmltext('<input type="submit" value="%s"/>') % _('Load')
1106
            r += htmltext('</form>')
1107

    
1108
        if get_cfg('aq-permissions', {}).get('links'):
1109
            r += self.links()
1110

    
1111
        cats = Category.select(order_by = 'name')
1112
        cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side']
1113
        Category.sort_by_position(cats)
1114
        if cats:
1115
            r += htmltext('<div id="side-services">')
1116
            r += htmltext('<h3>%s</h3>') % _('Services')
1117
            r += htmltext('<ul>')
1118
            for cat in cats:
1119
                r += htmltext('<li><a href="%s/">%s</a></li>') % (cat.url_name, cat.name)
1120
            r += htmltext('</ul>')
1121
            r += htmltext('</div>')
1122

    
1123
        if get_cfg('aq-permissions', {}).get('events') and Event.keys():
1124
            # if there are events, add a link to the agenda
1125
            tags = get_cfg('misc', {}).get('event_tags')
1126
            if not tags:
1127
                tags = get_default_event_tags()
1128
            r += htmltext('<h3 id="agenda-link"><a href="%sagenda/">%s</a></h3>') % (root_url, _('Agenda'))
1129

    
1130
            if path and path[0] == 'agenda':
1131
                r += htmltext('<p class="tags">')
1132
                for tag in tags:
1133
                    r += htmltext('<a href="%sagenda/tag/%s">%s</a> ') % (root_url, tag, tag)
1134
                r += htmltext('</p>')
1135
                r += self.agenda.display_remote_calendars()
1136

    
1137
                r += htmltext('<p>')
1138
                r += htmltext('  <a href="%sagenda/filter">%s</a>') % (root_url, _('Advanced Filter'))
1139
                r += htmltext('</p>')
1140

    
1141
        v = r.getvalue()
1142
        if v:
1143
            r = TemplateIO(html=True)
1144
            r += htmltext('<div id="sidebox">')
1145
            r += v
1146
            r += htmltext('</div>')
1147
            return r.getvalue()
1148

    
1149
        return None
1150

    
1151
    def has_anonymous_access_codes(self):
1152
        return any((x for x in FormDef.select() if x.enable_tracking_codes))
1153

    
1154
    def links(self):
1155
        links = Link.select()
1156
        if not links:
1157
            return ''
1158

    
1159
        Link.sort_by_position(links)
1160

    
1161
        r = TemplateIO(html=True)
1162

    
1163
        r += htmltext('<div id="links">')
1164
        if links[0].url:
1165
            # first link has an URL, so it's not a title, so we display a
1166
            # generic title
1167
            r += htmltext('<h3>%s</h3>') % _('Useful links')
1168
        has_ul = False
1169
        vars = get_publisher().substitutions.get_context_variables()
1170
        for link in links:
1171
            if not link.url:
1172
                # acting title
1173
                if has_ul:
1174
                    r += htmltext('</ul>')
1175
                r += htmltext('<h3>%s</h3>') % link.title
1176
                r += htmltext('<ul>')
1177
                has_ul = True
1178
            else:
1179
                if not has_ul:
1180
                    r += htmltext('<ul>')
1181
                    has_ul = True
1182
                r += htmltext('<li class="link-%s"><a href="%s">%s</a></li>') % (
1183
                        simplify(link.title), get_variadic_url(link.url, vars), link.title)
1184
        if has_ul:
1185
            r += htmltext('</ul>')
1186
        r += htmltext('</div>')
1187
        return r.getvalue()
1188

    
1189
    def announces(self):
1190
        announces = Announce.get_published_announces()
1191
        if not announces:
1192
            return
1193

    
1194
        r = TemplateIO(html=True)
1195
        r += htmltext('<div id="announces">')
1196
        r += htmltext('<h3>%s</h3>') % _('Announces to citizens')
1197
        for item in announces[:3]:
1198
            r += htmltext('<div class="announce-item">')
1199
            r += htmltext('<h4>')
1200
            if item.publication_time:
1201
                r += time.strftime(misc.date_format(), item.publication_time)
1202
                r += ' - '
1203
            r += item.title
1204
            r += htmltext('</h4>')
1205
            r += htmltext('<p>')
1206
            r += item.text
1207
            r += htmltext('</p>')
1208
            r += htmltext('</div>')
1209

    
1210
        r += htmltext('<ul id="announces-links">')
1211
        r += htmltext('<li><a href="announces/subscribe">%s</a></li>') % _('Receiving those Announces')
1212
        r += htmltext('<li><a href="announces/">%s</a></li>') % _('Previous Announces')
1213
        r += htmltext('</ul>')
1214
        r += htmltext('</div>')
1215
        return r.getvalue()
1216

    
1217
    def myspace_snippet(self):
1218
        r = TemplateIO(html=True)
1219
        r += htmltext('<div id="myspace">')
1220
        r += htmltext('<h3>%s</h3>') % _('My Space')
1221
        r += htmltext('<ul>')
1222
        if get_request().user and not get_request().user.anonymous:
1223
            r += htmltext('  <li><a href="myspace/" id="member">%s</a></li>') % _('Access to your personal space')
1224
            r += htmltext('  <li><a href="logout" id="logout">%s</a></li>') % _('Logout')
1225
        else:
1226
            r += htmltext('  <li><a href="register/" id="inscr">%s</a></li>') % _('Registration')
1227
            r += htmltext('  <li><a href="login/" id="login">%s</a></li>') % _('Login')
1228
        r += htmltext('</ul>')
1229
        r += htmltext('</div>')
1230
        return r.getvalue()
1231

    
1232
    def page_view(self, key, title, urlname = None):
1233
        if not urlname:
1234
            urlname = key[3:].replace(str('_'), str('-'))
1235
        get_response().breadcrumb.append((urlname, title))
1236
        template.html_top(title)
1237
        r = TemplateIO(html=True)
1238
        r += htmltext('<div class="article">')
1239
        r += htmltext(TextsDirectory.get_html_text(key))
1240
        r += htmltext('</div>')
1241
        return r.getvalue()
1242

    
1243
    def informations_editeur(self):
1244
        get_response().filter['bigdiv'] = 'info'
1245
        return self.page_view('aq-editor-info', _('Editor Informations'),
1246
                urlname = 'informations_editeur')
1247

    
1248
    def accessibility(self):
1249
        get_response().filter['bigdiv'] = 'accessibility'
1250
        return self.page_view('aq-accessibility', _('Accessibility Statement'))
1251

    
1252
    def contact(self):
1253
        get_response().filter['bigdiv'] = 'contact'
1254
        return self.page_view('aq-contact', _('Contact'))
1255

    
1256
    def help(self):
1257
        get_response().filter['bigdiv'] = 'help'
1258
        return self.page_view('aq-help', _('Help'))
1259

    
1260

    
1261
from qommon.publisher import get_publisher_class
1262
get_publisher_class().root_directory_class = AlternateRootDirectory
1263
get_publisher_class().after_login_url = 'myspace/'
1264
get_publisher_class().use_sms_feature = True
1265

    
1266
# help links
1267
get_publisher_class().backoffice_help_url = {
1268
    'fr': 'https://doc-publik.entrouvert.com/',
1269
}
1270

    
1271

    
1272
EmailsDirectory.register('announces-subscription-confirmation',
1273
        N_('Confirmation of Announces Subscription'),
1274
        N_('Available variables: change_url, cancel_url, time, sitename'),
1275
        default_subject = N_('Announce Subscription Request'),
1276
        default_body = N_("""\
1277
You have (or someone impersonating you has) requested to subscribe to
1278
announces from [sitename].  To confirm this request, visit the
1279
following link:
1280

    
1281
[confirm_url]
1282

    
1283
If you are not the person who made this request, or you wish to cancel
1284
this request, visit the following link:
1285

    
1286
[cancel_url]
1287

    
1288
If you do nothing, the request will lapse after 3 days (precisely on
1289
[time]).
1290
"""))
1291

    
1292

    
1293
TextsDirectory.register('aq-announces-subscription',
1294
        N_('Text on announces subscription page'),
1295
        default = N_('''\
1296
<p>
1297
FIXME
1298
'</p>'''))
1299

    
1300
TextsDirectory.register('aq-sms-demo',
1301
        N_('Text when subscribing to announces SMS and configured as demo'),
1302
        default = N_('''
1303
<p>
1304
Receiving announces by SMS is not possible in this demo
1305
</p>'''))
1306

    
1307
TextsDirectory.register('aq-editor-info', N_('Editor Informations'))
1308
TextsDirectory.register('aq-accessibility', N_('Accessibility Statement'))
1309
TextsDirectory.register('aq-contact', N_('Contact Information'))
1310
TextsDirectory.register('aq-help', N_('Help'))
1311
TextsDirectory.register('aq-sso-text',  N_('Connecting with Identity Provider'),
1312
        default = N_('''<h3>Connecting with Identity Provider</h3>
1313
<p>You can also use your identity provider to connect.
1314
</p>'''))
1315

    
1316
TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg = True)
(23-23/27)