Project

General

Profile

Download (43.4 KB) Statistics
| Branch: | Tag: | Revision:

root / extra / modules / root.ptl @ 5374ecec

1 42df9640 Frédéric Péters
from quixote import get_publisher, get_response, get_request, redirect, get_session
2 32ba0ff4 Frédéric Péters
from quixote.directory import Directory
3 4ee9f1b4 Frédéric Péters
from quixote.html import htmltext
4 a673a665 Frédéric Péters
from quixote.util import StaticDirectory
5 4ee9f1b4 Frédéric Péters
6
import os
7 76dabe9a Jérôme Schneider
import re
8 f0db9c17 Jérôme Schneider
import string
9 e5c0a39d Frédéric Péters
import urlparse
10
11 b5e52696 Frédéric Péters
try:
12
    import lasso
13
except ImportError:
14
    pass
15 4ee9f1b4 Frédéric Péters
16 05c98e5f Frédéric Péters
import wcs
17
import wcs.root
18 fde86923 Frédéric Péters
import qommon
19 b6daa136 Frédéric Péters
from qommon import get_cfg, get_logger
20 b1c812cb Frédéric Péters
from qommon import template
21
from qommon import errors
22
from qommon.form import *
23 0f477ab9 Frédéric Péters
from qommon import logger
24 c1b8f5f3 Frédéric Péters
from wcs.roles import logged_users_role
25 05c98e5f Frédéric Péters
26 b1c812cb Frédéric Péters
from qommon import emails
27 76dabe9a Jérôme Schneider
from qommon.sms import SMS
28 05c98e5f Frédéric Péters
from wcs.categories import Category
29 a673a665 Frédéric Péters
from wcs.formdef import FormDef, status_labels
30 b1c812cb Frédéric Péters
from qommon.tokens import Token
31
from qommon.admin.emails import EmailsDirectory
32 2d29ba83 Frédéric Péters
from qommon.admin.texts import TextsDirectory
33 05c98e5f Frédéric Péters
34 3be7cfa9 Frédéric Péters
from links import Link
35 8efa60ca Frédéric Péters
from announces import Announce, AnnounceSubscription
36 9c91e126 Frédéric Péters
from myspace import MyspaceDirectory
37 fa229320 Frédéric Péters
from agenda import AgendaDirectory
38 cfb41dcc Frédéric Péters
from payments import PublicPaymentDirectory
39 587ad081 Frédéric Péters
from events import Event, get_default_event_tags
40 3be7cfa9 Frédéric Péters
41 901b9cc8 Frédéric Péters
import admin
42
43 a673a665 Frédéric Péters
import wcs.forms.root
44
from wcs.workflows import Workflow
45
46 42c14444 Frédéric Péters
from saml2 import Saml2Directory
47
48 05c98e5f Frédéric Péters
OldRootDirectory = wcs.root.RootDirectory
49
50 e5c0a39d Frédéric Péters
import qommon.ident.password
51
import qommon.ident.idp
52
53 9d071a47 Frédéric Péters
import drupal
54 dab68f9e Thomas Noël
import ezldap_ui
55 9d071a47 Frédéric Péters
56 818bc7c2 Frédéric Péters
def category_get_homepage_position(self):
57
    if hasattr(self, 'homepage_position') and self.homepage_position:
58
        return self.homepage_position
59 aeda4490 Frédéric Péters
    if self.url_name == 'consultations':
60
        return '2nd'
61
    return '1st'
62 818bc7c2 Frédéric Péters
Category.get_homepage_position = category_get_homepage_position
63 a673a665 Frédéric Péters
64 fc4cb69d Frédéric Péters
def category_get_limit(self):
65
    if hasattr(self, 'limit') and self.limit is not None:
66
        return self.limit
67
    return 3
68
Category.get_limit = category_get_limit
69
70
71 a673a665 Frédéric Péters
class FormsRootDirectory(wcs.forms.root.RootDirectory):
72
73
    def user_forms [html] (self, user_forms):
74 a3f1a639 Frédéric Péters
        base_url = get_publisher().get_root_url()
75
76 a673a665 Frédéric Péters
        draft = [x for x in user_forms if x.status == 'draft']
77
        if draft:
78 08161821 Frédéric Péters
            '<h4 id="drafts">%s</h4>' % _('My Current Drafts')
79 a673a665 Frédéric Péters
            '<ul>'
80
            for f in draft:
81 a8fc192f Frédéric Péters
                '<li><a href="%s%s/%s/%s">%s</a></li>' % (base_url, 
82 a3f1a639 Frédéric Péters
                    f.formdef.category.url_name,
83 a673a665 Frédéric Péters
                    f.formdef.url_name, f.id, f.formdef.name)
84
            '</ul>'
85
86
87
        # (COMPAT) without workflows
88
        current = [x for x in user_forms if x.status in ('new', 'accepted')]
89
        if current:
90 08161821 Frédéric Péters
            '<h4 id="submitted">%s</h4>' % _('My Current Forms')
91 a673a665 Frédéric Péters
            '<ul>'
92
            for f in current:
93 4f714a98 Frédéric Péters
                if f.formdef is None:
94
                    continue
95 ab395ab7 Frédéric Péters
                if f.formdef.category_id:
96
                    category_url = f.formdef.category.url_name
97
                else:
98
                    category_url = '.'
99 a3f1a639 Frédéric Péters
                '<li><a href="%s%s/%s/%s/">%s</a>, %s, %s: %s</li>' % (
100
                    base_url,
101 ab395ab7 Frédéric Péters
                    category_url,
102 a673a665 Frédéric Péters
                    f.formdef.url_name, f.id, f.formdef.name, 
103
                    misc.localstrftime(f.receipt_time),
104
                    _('status'),
105
                    _(status_labels[f.status]) )
106
            '</ul>'
107
        done = [x for x in user_forms if x.status in ('rejected', 'finished')]
108
        if done:
109 08161821 Frédéric Péters
            '<h4 id="done">%s</h4>' % _('My Old Forms')
110 a673a665 Frédéric Péters
            '<ul>'
111
            for f in done:
112 4530a00a Frédéric Péters
                if not f.formdef:
113
                    continue
114 ab395ab7 Frédéric Péters
                if f.formdef.category_id:
115
                    category_url = f.formdef.category.url_name
116
                else:
117
                    category_url = '.'
118 a3f1a639 Frédéric Péters
                '<li><a href="%s%s/%s/%s/">%s</a>, %s, %s: %s</li>' % (
119
                    base_url,
120 ab395ab7 Frédéric Péters
                    category_url,
121 a673a665 Frédéric Péters
                    f.formdef.url_name, f.id, f.formdef.name, 
122
                    misc.localstrftime(f.receipt_time),
123
                    _('status'),
124
                    _(status_labels[f.status]) )
125
            '</ul>'
126
127
        # with workflows
128
        workflows = Workflow.select(order_by = 'name')
129
        for workflow in workflows:
130
            # XXX: seperate endpoints from non-endpoints
131
            for status in workflow.possible_status:
132
                fms = [x for x in user_forms if x.status == 'wf-%s' % status.id and \
133 85f94770 Frédéric Péters
                        x.formdef and x.formdef.workflow_id == workflow.id]
134 a673a665 Frédéric Péters
                if not fms:
135
                    continue
136 08161821 Frédéric Péters
                '<h4>%s</h4>' % _('My forms with status "%s"') % status.name
137 a673a665 Frédéric Péters
                '<ul>'
138
                for f in fms:
139 ab395ab7 Frédéric Péters
                    if f.formdef.category_id:
140
                        category_url = f.formdef.category.url_name
141
                    else:
142
                        category_url = '.'
143 a3f1a639 Frédéric Péters
                    '<li><a href="%s%s/%s/%s/">%s</a>, %s</li>' % (
144
                            base_url,
145 ab395ab7 Frédéric Péters
                            category_url,
146 a673a665 Frédéric Péters
                            f.formdef.url_name, f.id, f.formdef.name, 
147
                            misc.localstrftime(f.receipt_time))
148
                '</ul>'
149
150
151 613ca2d5 Frédéric Péters
class AnnounceDirectory(Directory):
152
    _q_exports = ['', 'edit', 'delete', 'email']
153
154
    def __init__(self, announce):
155
        self.announce = announce
156
157
    def _q_index [html] (self):
158
        template.html_top(_('Announces to citizens'))
159
160
        if self.announce.publication_time:
161
            date_heading = '%s - ' % time.strftime(misc.date_format(), self.announce.publication_time)
162
        else:
163
            date_heading = ''
164
165
        '<h3>%s%s</h3>' % (date_heading, self.announce.title)
166
167
        '<p>'
168
        self.announce.text
169
        '</p>'
170
171
        '<p>'
172
        '<a href="../">%s</a>' % _('Back')
173
        '</p>'
174
175
176 32ba0ff4 Frédéric Péters
class AnnouncesDirectory(Directory):
177 76dabe9a Jérôme Schneider
    _q_exports = ['', 'subscribe', 'email', 'atom', 'sms', 'emailconfirm',
178
            'email_unsubscribe', 'sms_unsubscribe', 'smsconfirm', 'rawlist']
179 8efa60ca Frédéric Péters
180 76dabe9a Jérôme Schneider
    
181 8efa60ca Frédéric Péters
    def _q_traverse(self, path):
182
        get_response().breadcrumb.append(('announces/', _('Announces')))
183
        return Directory._q_traverse(self, path)
184 32ba0ff4 Frédéric Péters
185 8d66bd48 Frédéric Péters
    def _q_index [html] (self):
186 0a8e1fe4 Frédéric Péters
        template.html_top(_('Announces to citizens'))
187
        self.announces_list()
188
        '<ul id="announces-links">'
189
        '<li><a href="subscribe">%s</a></li>' % _('Receiving those Announces')
190
        '</ul>'
191
192 76dabe9a Jérôme Schneider
    def _get_announce_subscription(self):
193
        """ """
194
        sub = None
195
        if get_request().user:
196
            subs = AnnounceSubscription.select(lambda x: x.user_id == get_request().user.id)
197
            if subs:
198
                sub = subs[0]
199
        return sub
200
201 0a8e1fe4 Frédéric Péters
    def rawlist [html] (self):
202
        self.announces_list()
203
        get_response().filter = None
204
205
    def announces_list [html] (self):
206 7038bf81 Frédéric Péters
        announces = Announce.get_published_announces()
207 8d66bd48 Frédéric Péters
        if not announces:
208
            raise errors.TraversalError()
209
210 3befb855 Frédéric Péters
        # XXX: will need pagination someday
211 8d66bd48 Frédéric Péters
        for item in announces:
212 0a8e1fe4 Frédéric Péters
            '<div class="announce-item">\n'
213 8d66bd48 Frédéric Péters
            '<h4>'
214 cd827b62 Frédéric Péters
            if item.publication_time:
215 7038bf81 Frédéric Péters
                time.strftime(misc.date_format(), item.publication_time)
216 cd827b62 Frédéric Péters
                ' - '
217 8d66bd48 Frédéric Péters
            item.title
218 0a8e1fe4 Frédéric Péters
            '</h4>\n'
219
            '<p>\n'
220 8d66bd48 Frédéric Péters
            item.text
221 0a8e1fe4 Frédéric Péters
            '\n</p>\n'
222
            '</div>\n'
223 8d66bd48 Frédéric Péters
224 32ba0ff4 Frédéric Péters
225 68f47a3e Frédéric Péters
    def sms [html] (self):
226
        sms_mode = get_cfg('sms', {}).get('mode', 'none')
227 e90eeb1a Frédéric Péters
228 68f47a3e Frédéric Péters
        if sms_mode == 'none':
229
            raise errors.TraversalError()
230
231
        get_response().breadcrumb.append(('sms', _('SMS')))
232
        template.html_top(_('Receiving announces by SMS'))
233
234
        if sms_mode == 'demo':
235 89274e51 Frédéric Péters
            TextsDirectory.get_html_text('aq-sms-demo')
236 76dabe9a Jérôme Schneider
        elif sms_mode == 'mobyt':
237 71f60c01 Benjamin Dauvergne
            announces_cfg = get_cfg('announces',{})
238
            mobile_mask = announces_cfg.get('mobile_mask')
239
            if mobile_mask:
240
                mobile_mask = ' (' + mobile_mask + ')'
241 cff9cb99 Benjamin Dauvergne
            else:
242
                mobile_mask = ''
243 76dabe9a Jérôme Schneider
            form = Form(enctype='multipart/form-data')
244 1db74521 Jérôme Schneider
            form.add(StringWidget, 'mobile', title = _('Mobile number %s') % mobile_mask, size=12, required=True)
245 76dabe9a Jérôme Schneider
            form.add_submit('submit', _('Subscribe'))
246
            form.add_submit('cancel', _('Cancel'))
247
248
            if form.get_submit() == 'cancel':
249
                return redirect('subscribe')
250
251
            if form.is_submitted() and not form.has_errors():
252
                s = self.sms_submit(form)
253
                if s == False:
254
                    form.render()
255
                else:
256
                    return redirect("smsconfirm")
257
            else:
258
                form.render()
259
260
    def sms_submit(self, form):
261
        mobile = form.get_widget("mobile").parse()
262 71f60c01 Benjamin Dauvergne
        # clean the string, remove any extra character
263
        mobile = re.sub('[^0-9+]','',mobile)
264
        # if a mask was set, validate
265
        announces_cfg = get_cfg('announces',{})
266
        mobile_mask = announces_cfg.get('mobile_mask')
267
        if mobile_mask:
268
            mobile_regexp = re.sub('X','[0-9]', mobile_mask) + '$'
269
            if not re.match(mobile_regexp, mobile):
270
                form.set_error("mobile", _("Phone number invalid ! It must match ") + mobile_mask)
271
                return False
272
        if mobile.startswith('00'):
273
            mobile = '+' + mobile[2:]
274
        else:
275
            # Default to france international prefix
276
            if not mobile.startswith('+'):
277
                mobile = re.sub("^0", "+33", mobile)
278 76dabe9a Jérôme Schneider
        sub = self._get_announce_subscription()
279
        if not sub:
280
            sub = AnnounceSubscription()
281
        if get_request().user:
282
            sub.user_id = get_request().user.id
283
284
        if mobile:
285
            sub.sms = mobile
286
287
        if not get_request().user:
288
            sub.enabled = False
289
290
        sub.store()
291
292
        # Asking sms confirmation
293 f0db9c17 Jérôme Schneider
        token = Token(3 * 86400, 4, string.digits)
294 76dabe9a Jérôme Schneider
        token.type = 'announces-subscription-confirmation'
295
        token.subscription_id = sub.id
296
        token.store()
297
298 f0db9c17 Jérôme Schneider
        message = _("Confirmation code : %s" % token.id)
299 76dabe9a Jérôme Schneider
        sms_cfg = get_cfg('sms', {})
300
        sms = SMS()
301
        try:
302
            sms.send([mobile], message, sms_cfg.get('sender', 'auquotidien'))
303
        except errors.SMSError, e:
304
            get_logger().error(e)
305
            form.set_error("mobile", _("Send SMS confirmation failed"))
306
            sub.remove("sms")
307
            return False
308
309
    def smsconfirm [html] (self):
310
        template.html_top(_('Receiving announces by SMS confirmation'))
311
        "<p>%s</p>" % _("You will receive a confirmation code by SMS.")
312
        form = Form(enctype='multipart/form-data')
313
        form.add(StringWidget, 'code', title = _('Confirmation code (4 characters)'), size=12, required=True)
314
        form.add_submit('submit', _('Subscribe'))
315
        form.add_submit('cancel', _('Cancel'))
316
317
        if form.is_submitted() and not form.has_errors():
318
            token = None
319
            id = form.get_widget("code").parse()
320
            try:
321
                token = Token.get(id)
322
            except KeyError:
323
                form.set_error("code",  _('Invalid confirmation code.'))
324
            else:
325 8554d19e Frédéric Péters
                if token.type != 'announces-subscription-confirmation':
326
                    form.set_error("code",  _('Invalid confirmation code.'))
327
                else:
328
                    sub = AnnounceSubscription.get(token.subscription_id)
329
                    token.remove_self()
330
                    sub.enabled_sms = True
331
                    sub.store()
332
                    return redirect('.')
333 76dabe9a Jérôme Schneider
            form.render()
334
        else:
335
            form.render()
336
337
    def sms_unsubscribe [html] (self):
338
        sub = self._get_announce_subscription()
339
340
        form = Form(enctype='multipart/form-data')
341
        if not sub:
342
            return redirect('..')
343
344
        form.add_submit('submit', _('Unsubscribe'))
345
        form.add_submit('cancel', _('Cancel'))
346
347
        if form.get_submit() == 'cancel':
348
            return redirect('..')
349
350
        get_response().breadcrumb.append(('sms', _('SMS Unsubscription')))
351
        template.html_top()
352
353
        if form.is_submitted() and not form.has_errors():
354
            if sub:
355
                sub.remove("sms")
356
357
            def sms_unsub_ok [html] ():
358
                root_url = get_publisher().get_root_url()
359
                '<p>'
360
                _('You have been unsubscribed from announces')
361
                '</p>'
362 c465777a Frédéric Péters
                if not get_response().iframe_mode:
363
                    '<a href="%s">%s</a>' % (root_url, _('Back Home'))
364 76dabe9a Jérôme Schneider
365
            return sms_unsub_ok()
366
367 68f47a3e Frédéric Péters
        else:
368 76dabe9a Jérôme Schneider
            '<p>'
369
            _('Do you want to stop receiving announces by sms ?')
370
            '</p>'
371
            form.render()
372 e90eeb1a Frédéric Péters
373 8efa60ca Frédéric Péters
374 32ba0ff4 Frédéric Péters
    def subscribe [html] (self):
375 8efa60ca Frédéric Péters
        get_response().breadcrumb.append(('subscribe', _('Subscription')))
376 32ba0ff4 Frédéric Péters
        template.html_top(_('Receiving Announces'))
377
378 89274e51 Frédéric Péters
        TextsDirectory.get_html_text('aq-announces-subscription')
379 32ba0ff4 Frédéric Péters
380 76dabe9a Jérôme Schneider
        sub = self._get_announce_subscription()
381 7f8fbe7e Frédéric Péters
382 ff235e28 Frédéric Péters
        '<ul id="announce-modes">'
383 76dabe9a Jérôme Schneider
        if sub and sub.email:
384 7f8fbe7e Frédéric Péters
            ' <li>'
385 76dabe9a Jérôme Schneider
            '<span id="par_mail">%s</span>' % _('Email (currently subscribed)')
386 7f8fbe7e Frédéric Péters
            ' <a href="email_unsubscribe" rel="popup">%s</a></li>' % _('Unsubscribe')
387
        else:
388
            ' <li><a href="email" id="par_mail" rel="popup">%s</a></li>' % _('Email')
389 76dabe9a Jérôme Schneider
        if sub and sub.sms:
390
            ' <li>'
391
            if sub.enabled_sms:
392 807817db Jérôme Schneider
                '<span id="par_sms">%s</span>' % _('SMS %s (currently subscribed)') % sub.sms
393 76dabe9a Jérôme Schneider
            else:
394 807817db Jérôme Schneider
                '<span id="par_sms">%s</span>' % _('SMS %s (currently not confirmed)') % sub.sms
395 76dabe9a Jérôme Schneider
                ' <a href="smsconfirm" rel="popup">%s</a> ' % _('Confirmation')
396
            ' <a href="sms_unsubscribe" rel="popup">%s</a></li>' % _('Unsubscribe')
397
        elif get_cfg('sms', {}).get('mode', 'none') != 'none':
398 68f47a3e Frédéric Péters
            ' <li><a href="sms" id="par_sms">%s</a></li>' % _('SMS')
399 b7a2808c Frédéric Péters
        ' <li><a class="feed-link" href="atom" id="par_rss">%s</a>' % _('Feed')
400 32ba0ff4 Frédéric Péters
        '</ul>'
401
402
403
    def email [html] (self):
404 8efa60ca Frédéric Péters
        get_response().breadcrumb.append(('email', _('Email Subscription')))
405 32ba0ff4 Frédéric Péters
        template.html_top(_('Receiving Announces by email'))
406
407
        form = Form(enctype='multipart/form-data')
408
        if get_request().user:
409
            if get_request().user.email:
410 ff235e28 Frédéric Péters
                '<p>'
411 32ba0ff4 Frédéric Péters
                _('You are logged in and your email is %s, ok to subscribe ?') % \
412
                    get_request().user.email
413 ff235e28 Frédéric Péters
                '</p>'
414 32ba0ff4 Frédéric Péters
                form.add_submit('submit', _('Subscribe'))
415
            else:
416 ff235e28 Frédéric Péters
                '<p>'
417 8efa60ca Frédéric Péters
                _("You are logged in but there is no email address in your profile.")
418 ff235e28 Frédéric Péters
                '</p>'
419 32ba0ff4 Frédéric Péters
                form.add(EmailWidget, 'email', title = _('Email'), required = True)
420
                form.add_submit('submit', _('Subscribe'))
421
                form.add_submit('submit-remember', _('Subscribe and add this email to my profile'))
422
        else:
423
            '<p>'
424
            _('FIXME will only be used for this purpose etc.')
425
            '</p>'
426
            form.add(EmailWidget, 'email', title = _('Email'), required = True)
427
            form.add_submit('submit', _('Subscribe'))
428
        
429
        form.add_submit('cancel', _('Cancel'))
430
431
        if form.get_submit() == 'cancel':
432
            return redirect('subscribe')
433
434
        if form.is_submitted() and not form.has_errors():
435 8efa60ca Frédéric Péters
            s = self.email_submit(form)
436
            if s is not False:
437
                return s
438 32ba0ff4 Frédéric Péters
        else:
439
            form.render()
440
441 8efa60ca Frédéric Péters
    def email_submit(self, form):
442 76dabe9a Jérôme Schneider
        sub = self._get_announce_subscription()
443
        if not sub:
444
            sub = AnnounceSubscription()
445 8efa60ca Frédéric Péters
446
        if get_request().user:
447
            sub.user_id = get_request().user.id
448
449
        if form.get_widget('email'):
450
            sub.email = form.get_widget('email').parse()
451 76dabe9a Jérôme Schneider
        elif get_request().user.email:
452
            sub.email = get_request().user.email
453 8efa60ca Frédéric Péters
454
        if not get_request().user:
455
            sub.enabled = False
456
457
        sub.store()
458
459
        if get_request().user:
460
            def email_submit_ok [html] ():
461 8097c060 Frédéric Péters
                root_url = get_publisher().get_root_url()
462 8efa60ca Frédéric Péters
                '<p>'
463
                _('You have been subscribed to the announces.')
464
                '</p>'
465 c465777a Frédéric Péters
                if not get_response().iframe_mode:
466
                    '<a href="%s">%s</a>' % (root_url, _('Back Home'))
467 8efa60ca Frédéric Péters
468
            return email_submit_ok()
469
470
        # asking email confirmation before subscribing someone
471
        token = Token(3 * 86400)
472
        token.type = 'announces-subscription-confirmation'
473
        token.subscription_id = sub.id
474
        token.store()
475
        data = {
476
            'confirm_url': get_request().get_url() + 'confirm?t=%s&a=cfm' % token.id,
477
            'cancel_url': get_request().get_url() + 'confirm?t=%s&a=cxl' % token.id,
478
            'time': misc.localstrftime(time.localtime(token.expiration)),
479
        }
480
481
        emails.custom_ezt_email('announces-subscription-confirmation',
482 89274e51 Frédéric Péters
                data, sub.email, exclude_current_user = False)
483 8efa60ca Frédéric Péters
484
        def email_submit_ok [html] ():
485 8097c060 Frédéric Péters
            root_url = get_publisher().get_root_url()
486 8efa60ca Frédéric Péters
            '<p>'
487
            _('You have been sent an email for confirmation')
488
            '</p>'
489 c465777a Frédéric Péters
            if not get_response().iframe_mode:
490
                '<a href="%s">%s</a>' % (root_url, _('Back Home'))
491 8efa60ca Frédéric Péters
492
        return email_submit_ok()
493
494
    def emailconfirm(self):
495
        tokenv = get_request().form.get('t')
496
        action = get_request().form.get('a')
497
498 59b3ffe6 Frédéric Péters
        root_url = get_publisher().get_root_url()
499
500 8efa60ca Frédéric Péters
        try:
501
            token = Token.get(tokenv)
502
        except KeyError:
503
            return template.error_page(
504
                    _('The token you submitted does not exist, has expired, or has been cancelled.'),
505 59b3ffe6 Frédéric Péters
                    continue_to = (root_url, _('home page')))
506 8efa60ca Frédéric Péters
507
        if token.type != 'announces-subscription-confirmation':
508
            return template.error_page(
509
                    _('The token you submitted is not appropriate for the requested task.'),
510 59b3ffe6 Frédéric Péters
                    continue_to = (root_url, _('home page')))
511 8efa60ca Frédéric Péters
512
        sub = AnnounceSubscription.get(token.subscription_id)
513
514
        if action == 'cxl':
515
            def cancel [html]():
516 8097c060 Frédéric Péters
                root_url = get_publisher().get_root_url()
517 8b022547 Frédéric Péters
                template.html_top(_('Email Subscription'))
518 8efa60ca Frédéric Péters
                '<h1>%s</h1>' % _('Request Cancelled')
519
                '<p>%s</p>' % _('The request for subscription has been cancelled.')
520
                '<p>'
521 8097c060 Frédéric Péters
                htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
522 8efa60ca Frédéric Péters
                '</p>'
523
            token.remove_self()
524
            sub.remove_self()
525
            return cancel()
526
527
        if action == 'cfm':
528 a4426420 Frédéric Péters
            token.remove_self()
529 8efa60ca Frédéric Péters
            sub.enabled = True
530
            sub.store()
531
            def sub [html] ():
532 8097c060 Frédéric Péters
                root_url = get_publisher().get_root_url()
533 8b022547 Frédéric Péters
                template.html_top(_('Email Subscription'))
534 8efa60ca Frédéric Péters
                '<h1>%s</h1>' % _('Subscription Confirmation')
535
                '<p>%s</p>' % _('Your subscription to announces is now effective.')
536
                '<p>'
537 8097c060 Frédéric Péters
                htmltext(_('Continue to <a href="%s">home page</a>') % root_url)
538 8efa60ca Frédéric Péters
                '</p>'
539
            return sub()
540
541
542 b278d5d1 Frédéric Péters
    def atom [plain] (self):
543
        response = get_response()
544
        response.set_content_type('application/atom+xml')
545 e90eeb1a Frédéric Péters
546 b278d5d1 Frédéric Péters
        from pyatom import pyatom
547
        xmldoc = pyatom.XMLDoc()
548
        feed = pyatom.Feed()
549
        xmldoc.root_element = feed
550
        feed.title = get_cfg('misc', {}).get('sitename', 'Au Quotidien')
551
        feed.id = get_request().get_url()
552 e90eeb1a Frédéric Péters
553 e9792bb1 Frédéric Péters
        author_email = get_cfg('emails', {}).get('reply_to')
554
        if not author_email:
555
            author_email = get_cfg('emails', {}).get('from')
556
        if author_email:
557
            feed.authors.append(pyatom.Author(author_email))
558
559 7038bf81 Frédéric Péters
        announces = Announce.get_published_announces()
560 b278d5d1 Frédéric Péters
561
        if announces and announces[0].modification_time:
562
            feed.updated = misc.format_time(announces[0].modification_time,
563
                        '%(year)s-%(month)02d-%(day)02dT%(hour)02d:%(minute)02d:%(second)02dZ',
564
                        gmtime = True)
565 a84440b2 Frédéric Péters
        feed.links.append(pyatom.Link(get_request().get_url(1) + '/'))
566 b278d5d1 Frédéric Péters
567
        for item in announces:
568
            entry = item.get_atom_entry()
569
            if entry:
570
                feed.entries.append(entry)
571 e90eeb1a Frédéric Péters
572 b278d5d1 Frédéric Péters
        str(feed)
573 32ba0ff4 Frédéric Péters
574 7f8fbe7e Frédéric Péters
    def email_unsubscribe [html] (self):
575 76dabe9a Jérôme Schneider
        sub = self._get_announce_subscription()
576 7f8fbe7e Frédéric Péters
577
        form = Form(enctype='multipart/form-data')
578
        if not sub:
579
            form.add(EmailWidget, 'email', title = _('Email'), required = True)
580
581
        form.add_submit('submit', _('Unsubscribe'))
582
        form.add_submit('cancel', _('Cancel'))
583
584
        if form.get_submit() == 'cancel':
585
            return redirect('..')
586
587
        get_response().breadcrumb.append(('email', _('Email Unsubscription')))
588
        template.html_top()
589
590
        if form.is_submitted() and not form.has_errors():
591
            if sub:
592 76dabe9a Jérôme Schneider
                sub.remove("email")
593 7f8fbe7e Frédéric Péters
            else:
594
                email = form.get_widget('email').parse()
595 8097b5e0 Frédéric Péters
                for s in AnnounceSubscription.select():
596 7f8fbe7e Frédéric Péters
                    if s.email == email:
597 76dabe9a Jérôme Schneider
                        s.remove("email")
598 7f8fbe7e Frédéric Péters
599
            def email_unsub_ok [html] ():
600 8097c060 Frédéric Péters
                root_url = get_publisher().get_root_url()
601 7f8fbe7e Frédéric Péters
                '<p>'
602
                _('You have been unsubscribed from announces')
603
                '</p>'
604 c465777a Frédéric Péters
                if not get_response().iframe_mode:
605
                    '<a href="%s">%s</a>' % (root_url, _('Back Home'))
606 7f8fbe7e Frédéric Péters
607 b965bbbe Frédéric Péters
            return email_unsub_ok()
608
609 7f8fbe7e Frédéric Péters
        else:
610
            '<p>'
611
            _('Do you want to stop receiving announces by email?')
612
            '</p>'
613
            form.render()
614
615 613ca2d5 Frédéric Péters
    def _q_lookup(self, component):
616
        try:
617
            announce = Announce.get(component)
618
        except KeyError:
619
            raise errors.TraversalError()
620 8979a156 Frédéric Péters
621 d8a8676c Frédéric Péters
        if announce.hidden:
622 8979a156 Frédéric Péters
            raise errors.TraversalError()
623
624 613ca2d5 Frédéric Péters
        get_response().breadcrumb.append((str(announce.id), announce.title))
625
        return AnnounceDirectory(announce)
626 32ba0ff4 Frédéric Péters
627 b7a2808c Frédéric Péters
OldRegisterDirectory = wcs.root.RegisterDirectory
628
629
class AlternateRegisterDirectory(OldRegisterDirectory):
630
    def _q_traverse(self, path):
631
        get_response().filter['bigdiv'] = 'new_member'
632
        return OldRegisterDirectory._q_traverse(self, path)
633
634 0f477ab9 Frédéric Péters
    def _q_index [html] (self):
635 93b7c686 Frédéric Péters
        get_logger().info('register')
636 0f477ab9 Frédéric Péters
        ident_methods = get_cfg('identification', {}).get('methods', [])
637
638
        if len(ident_methods) == 0:
639
            idps = get_cfg('idp', {})
640
            if len(idps) == 0:
641
                return template.error_page(_('Authentication subsystem is not yet configured.'))
642
            ident_methods = ['idp'] # fallback to old behaviour; liberty.
643
644
        if len(ident_methods) == 1:
645
            method = ident_methods[0]
646 ffffccd8 Frédéric Péters
        else:
647
            method = 'password'
648 8ed05a37 Frédéric Péters
            return qommon.ident.register(method)
649 0f477ab9 Frédéric Péters
650
        if method == 'idp':
651 59b3ffe6 Frédéric Péters
            root_url = get_publisher().get_root_url()
652
            return redirect('%slogin' % root_url)
653 0f477ab9 Frédéric Péters
654
        return OldRegisterDirectory._q_index(self)
655 b7a2808c Frédéric Péters
656
OldLoginDirectory = wcs.root.LoginDirectory
657
658
class AlternateLoginDirectory(OldLoginDirectory):
659
    def _q_traverse(self, path):
660
        get_response().filter['bigdiv'] = 'member'
661
        return OldLoginDirectory._q_traverse(self, path)
662
663 b6daa136 Frédéric Péters
    def _q_index [html] (self):
664
        get_logger().info('login')
665
        ident_methods = get_cfg('identification', {}).get('methods', [])
666
667 e5c0a39d Frédéric Péters
        if len(ident_methods) > 1 and 'idp' in ident_methods:
668
            # if there is more than one identification method, and there is a
669
            # possibility of SSO, if we got there as a consequence of an access
670
            # unauthorized url on admin/ or backoffice/, then idp auth method
671
            # is chosen forcefully.
672
            after_url = get_session().after_url
673
            if after_url:
674 a21e96d6 Frédéric Péters
                root_url = get_publisher().get_root_url()
675 e5c0a39d Frédéric Péters
                after_path = urlparse.urlparse(after_url)[2]
676 a21e96d6 Frédéric Péters
                after_path = after_path[len(root_url):]
677
                if after_path.startswith(str('admin')) or \
678
                        after_path.startswith(str('backoffice')):
679 e5c0a39d Frédéric Péters
                    ident_methods = ['idp']
680
681 b6daa136 Frédéric Péters
        # don't display authentication system choice
682 e5c0a39d Frédéric Péters
        if len(ident_methods) == 1:
683
            method = ident_methods[0]
684
            try:
685
                return qommon.ident.login(method)
686
            except KeyError:
687
                get_logger().error('failed to login with method %s' % method)
688
                return errors.TraversalError()
689
690
        if sorted(ident_methods) == ['idp', 'password']:
691 816b457b Frédéric Péters
            get_response().breadcrumb.append(('login', _('Login')))
692 e5c0a39d Frédéric Péters
            identities_cfg = get_cfg('identities', {})
693
            form = Form(enctype = 'multipart/form-data', id = 'login-form', use_tokens = False)
694
            if identities_cfg.get('email-as-username', False):
695
                form.add(StringWidget, 'username', title = _('Email'), size=25, required=True)
696
            else:
697
                form.add(StringWidget, 'username', title = _('Username'), size=25, required=True)
698
            form.add(PasswordWidget, 'password', title = _('Password'), size=25, required=True)
699
            form.add_submit('submit', _('Connect'))
700
            if form.is_submitted() and not form.has_errors():
701
                tmp = qommon.ident.password.MethodDirectory().login_submit(form)
702
                if not form.has_errors():
703
                    return tmp
704
705
            '<div id="login-password">'
706
            get_session().display_message()
707
            form.render()
708 b6daa136 Frédéric Péters
709 f311c7dc Frédéric Péters
            base_url = get_publisher().get_root_url()
710
            '<p><a href="%sident/password/forgotten">%s</a></p>' % (
711
                    base_url, _('Forgotten password ?'))
712 e5c0a39d Frédéric Péters
713
            '</div>'
714
715
            # XXX: this part only supports a single IdP
716
            '<div id="login-sso">'
717
            TextsDirectory.get_html_text('aq-sso-text')
718 05303332 Frédéric Péters
            form = Form(enctype='multipart/form-data',
719
                    action = '%sident/idp/login' % base_url)
720 e5c0a39d Frédéric Péters
            form.add_hidden('method', 'idp')
721
            for kidp, idp in get_cfg('idp', {}).items():
722
                p = lasso.Provider(lasso.PROVIDER_ROLE_IDP,
723
                        misc.get_abs_path(idp['metadata']),
724
                        misc.get_abs_path(idp.get('publickey')), None)
725
                form.add_hidden('idp', p.providerId)
726
                break
727
            form.add_submit('submit', _('Connect'))
728
            
729
            form.render()
730
            '</div>'
731
732
            get_request().environ['REQUEST_METHOD'] = 'GET'
733
734
            """<script type="text/javascript">
735
              document.getElementById('login-form')['username'].focus();
736
            </script>"""
737
738
        else:
739
            return OldLoginDirectory._q_index(self)
740 32ba0ff4 Frédéric Péters
741
742 974e8f3c Frédéric Péters
OldIdentDirectory = wcs.root.IdentDirectory
743
class AlternateIdentDirectory(OldIdentDirectory):
744
    def _q_traverse(self, path):
745
        get_response().filter['bigdiv'] = 'member'
746
        return OldIdentDirectory._q_traverse(self, path)
747
748
749 05c98e5f Frédéric Péters
class AlternateRootDirectory(OldRootDirectory):
750 0c9e236d Frédéric Péters
    _q_exports = ['', 'admin', 'backoffice', 'forms', 'login', 'logout',
751 dc77e2e3 Frédéric Péters
            'liberty', 'token', 'saml', 'register', 'ident', 'afterjobs',
752 32ba0ff4 Frédéric Péters
            ('informations-editeur', 'informations_editeur'), 'index2',
753
            ('announces', 'announces_dir'),
754 9c91e126 Frédéric Péters
            'accessibility', 'contact', 'help',
755 b5e52696 Frédéric Péters
            'myspace', 'services', 'agenda',
756 5374ecec Frédéric Péters
            'themes', 'pages', 'payment', 'accesscode']
757 32ba0ff4 Frédéric Péters
758 901b9cc8 Frédéric Péters
    admin = admin.AdminRootDirectory()
759 32ba0ff4 Frédéric Péters
    announces_dir = AnnouncesDirectory()
760 b7a2808c Frédéric Péters
    register = AlternateRegisterDirectory()
761
    login = AlternateLoginDirectory()
762 974e8f3c Frédéric Péters
    ident = AlternateIdentDirectory()
763 9c91e126 Frédéric Péters
    myspace = MyspaceDirectory()
764 fa229320 Frédéric Péters
    agenda = AgendaDirectory()
765 42c14444 Frédéric Péters
    saml = Saml2Directory()
766 cfb41dcc Frédéric Péters
    payment = PublicPaymentDirectory()
767 05c98e5f Frédéric Péters
768 a673a665 Frédéric Péters
    def _q_traverse(self, path):
769 9d071a47 Frédéric Péters
        drupal.try_auth()
770 dab68f9e Thomas Noël
        ezldap_ui.try_auth(self)
771 9d071a47 Frédéric Péters
772 a3f1a639 Frédéric Péters
        session = get_session()
773
        if session:
774
            get_request().user = session.get_user()
775
        else:
776
            get_request().user = None
777
778 78d76e15 Thomas Noël
        get_publisher().substitutions.feed(get_request().user)
779
780 a673a665 Frédéric Péters
        response = get_response()
781
        if not hasattr(response, 'filter'):
782
            response.filter = {}
783 eb24b1dd Frédéric Péters
        response.filter['gauche'] = self.box_side(path)
784 28b7b336 Frédéric Péters
        response.filter['keywords'] = template.get_current_theme().get('keywords')
785 a3f1a639 Frédéric Péters
        response.breadcrumb = [ ('', _('Home')) ]
786
787
        if not self.admin:
788
            self.admin = get_publisher().admin_directory_class()
789
790
        if not self.backoffice:
791
            self.backoffice = get_publisher().backoffice_directory_class()
792
793
        try:
794
            return Directory._q_traverse(self, path)
795 4ec9e188 Frédéric Péters
        except errors.TraversalError, e:
796
            try:
797
                f = FormDef.get_by_urlname(path[0])
798
            except KeyError:
799
                pass
800
            else:
801 cab0c005 Frédéric Péters
                base_url = get_publisher().get_root_url()
802 0a3b6f01 Benjamin Dauvergne
803 cab0c005 Frédéric Péters
                uri_rest = get_request().environ.get('REQUEST_URI')
804 0a3b6f01 Benjamin Dauvergne
                if not uri_rest:
805
                    uri_rest = get_request().get_path()
806 cab0c005 Frédéric Péters
                if uri_rest.startswith(base_url):
807
                    uri_rest = uri_rest[len(base_url):]
808 069fda88 Thomas Noël
                elif uri_rest.startswith('/'):
809
                    # dirty hack, ezldap reverseproxy uses a fake base_url
810
                    uri_rest = uri_rest[1:]
811 591b96d6 Frédéric Péters
                if f.category_id:
812
                    return redirect('%s%s/%s' % (base_url, f.category.url_name, uri_rest))
813 cab0c005 Frédéric Péters
814 4ec9e188 Frédéric Péters
            raise e
815 a3f1a639 Frédéric Péters
816 a673a665 Frédéric Péters
817
    def _q_lookup(self, component):
818 58135dc8 Frédéric Péters
        if component == 'qo':
819
            dirname = os.path.join(get_publisher().data_dir, 'qommon')
820
            return StaticDirectory(dirname, follow_symlinks = True)
821 a673a665 Frédéric Péters
822 6bd8d84f Benjamin Dauvergne
        if component in ('css','images'):
823
            return OldRootDirectory._q_lookup(self, component)
824
825 a673a665 Frédéric Péters
        # is this a category ?
826
        try:
827
            category = Category.get_by_urlname(component)
828
        except KeyError:
829
            pass
830
        else:
831
            return FormsRootDirectory(category)
832
833 591b96d6 Frédéric Péters
        # is this a formdef ?
834
        try:
835
            formdef = FormDef.get_by_urlname(component)
836
        except KeyError:
837
            pass
838
        else:
839
            if formdef.category_id is None:
840
                return FormsRootDirectory()._q_lookup(component)
841
            # if there is category, let it fall back to raise TraversalError,
842
            # it will get caught in _q_traverse that will redirect it to an
843
            # URL embedding the category
844
845 a3f1a639 Frédéric Péters
        return None
846 a673a665 Frédéric Péters
847
848 05c98e5f Frédéric Péters
    def _q_index [html] (self):
849 59b3ffe6 Frédéric Péters
        root_url = get_publisher().get_root_url()
850 78631659 Frédéric Péters
        if get_request().user and get_request().user.anonymous and get_request().user.lasso_dump:
851 59b3ffe6 Frédéric Péters
            return redirect('%smyspace/new' % root_url)
852 b863d18f Frédéric Péters
853 42df9640 Frédéric Péters
        if get_response().iframe_mode:
854
            # never display home page in an iframe
855 59b3ffe6 Frédéric Péters
            return redirect('%sservices' % root_url)
856 42df9640 Frédéric Péters
857 32ba0ff4 Frédéric Péters
        template.html_top()
858 05c98e5f Frédéric Péters
859 0009f81f Frédéric Péters
        t = TextsDirectory.get_html_text('aq-home-page')
860
        if t:
861
            '<div id="home-page-intro">'
862
            t
863
            '</div>'
864
865
866 b7a2808c Frédéric Péters
        '<div id="centre">'
867 aeda4490 Frédéric Péters
        self.box_services(position='1st')
868 b08ecb38 Frédéric Péters
        '</div>'
869
        '<div id="droite">'
870 0c7d90c5 Frédéric Péters
        self.myspace_snippet()
871 aeda4490 Frédéric Péters
        self.box_services(position='2nd')
872 b7a2808c Frédéric Péters
        self.consultations()
873 b08ecb38 Frédéric Péters
        self.announces()
874
        '</div>'
875
876
    def services [html] (self):
877 dd7508b5 Frédéric Péters
        template.html_top()
878 9d59704c Frédéric Péters
        get_response().filter['bigdiv'] = 'rub_service'
879
        self.box_services(level = 2)
880 dd7508b5 Frédéric Péters
881 aeda4490 Frédéric Péters
    def box_services [html] (self, level=3, position=None):
882 05c98e5f Frédéric Péters
        ## Services
883 c1b8f5f3 Frédéric Péters
        if get_request().user and get_request().user.roles:
884
            accepted_roles = get_request().user.roles
885
        else:
886
            accepted_roles = []
887
888 46c896b9 Frédéric Péters
        cats = Category.select(order_by = 'name')
889 aeda4490 Frédéric Péters
        cats = [x for x in cats if x.url_name != 'consultations']
890 46c896b9 Frédéric Péters
        Category.sort_by_position(cats)
891 dfe32f4f Frédéric Péters
892 1eaca06e Thomas Noël
        all_formdefs = FormDef.select(lambda x: (not x.disabled or x.disabled_redirection)
893
                or x.always_advertise, order_by = 'name')
894 dfe32f4f Frédéric Péters
895 aeda4490 Frédéric Péters
        if position:
896
            t = self.display_list_of_formdefs(
897 6d9d9150 Frédéric Péters
                            [x for x in cats if x.get_homepage_position() == position],
898 aeda4490 Frédéric Péters
                            all_formdefs, accepted_roles)
899
        else:
900
            t = self.display_list_of_formdefs(cats, all_formdefs, accepted_roles)
901
902
        if not t:
903
            return
904
905
        if position == '2nd':
906
            '<div id="services-2nd">'
907
        else:
908
            '<div id="services">'
909
        if level == 2:
910
            '<h2>%s</h2>' % _('Services')
911
        else:
912 9d071a47 Frédéric Péters
            '<h3>%s</h3>' % _('Services')
913 aeda4490 Frédéric Péters
914 9f803542 Frédéric Péters
        if get_response().iframe_mode:
915
            if get_request().user:
916
                message = TextsDirectory.get_html_text('welcome-logged')
917
            else:
918
                message = TextsDirectory.get_html_text('welcome-unlogged')
919
920
            if message:
921
                '<div id="welcome-message">'
922
                message
923
                '</div>'
924
925 aeda4490 Frédéric Péters
        '<ul>'
926
        t
927
        '</ul>'
928
929
        '</div>'
930
931
    def display_list_of_formdefs [html] (self, cats, all_formdefs, accepted_roles):
932 46c896b9 Frédéric Péters
        for category in cats:
933 05c98e5f Frédéric Péters
            if category.url_name == 'consultations':
934 b08ecb38 Frédéric Péters
                self.consultations_category = category
935 05c98e5f Frédéric Péters
                continue
936 dfe32f4f Frédéric Péters
            formdefs = [x for x in all_formdefs if x.category_id == category.id]
937 1eaca06e Thomas Noël
            formdefs_advertise = []
938 c1b8f5f3 Frédéric Péters
939
            for formdef in formdefs[:]:
940 1eaca06e Thomas Noël
                if formdef.disabled: # is a redirection
941
                    continue
942 c1b8f5f3 Frédéric Péters
                if not formdef.roles:
943
                    continue
944
                if not get_request().user:
945 1eaca06e Thomas Noël
                    if formdef.always_advertise:
946
                        formdefs_advertise.append(formdef)
947 c1b8f5f3 Frédéric Péters
                    formdefs.remove(formdef)
948
                    continue
949
                if logged_users_role().id in formdef.roles:
950
                    continue
951
                for q in accepted_roles:
952
                    if q in formdef.roles:
953
                        break
954 eac4c202 Frédéric Péters
                else:
955 1eaca06e Thomas Noël
                    if formdef.always_advertise:
956
                        formdefs_advertise.append(formdef)
957 eac4c202 Frédéric Péters
                    formdefs.remove(formdef)
958 c1b8f5f3 Frédéric Péters
959 1eaca06e Thomas Noël
            if not formdefs and not formdefs_advertise:
960 c1b8f5f3 Frédéric Péters
                continue
961
962 05c98e5f Frédéric Péters
            '<li>'
963
            '<strong>'
964
            '<a href="%s/">' % category.url_name
965
            category.name
966 c2ffbce0 Frédéric Péters
            '</a></strong>\n'
967 ee8a8fd2 Frédéric Péters
            if category.description:
968
                '<p>'
969
                category.description
970
                '</p>'
971 c2ffbce0 Frédéric Péters
            '<ul>'
972 fc4cb69d Frédéric Péters
            limit = category.get_limit()
973
            for formdef in formdefs[:limit]:
974 c2ffbce0 Frédéric Péters
                '<li>'
975 5f20613a Thomas Noël
                if not formdef.disabled:
976 1eaca06e Thomas Noël
                    '<a href="%s/%s/">%s</a>' % (category.url_name, formdef.url_name, formdef.name)
977 5f20613a Thomas Noël
                else: # redirection
978
                    '<a href="%s">%s</a>' % (formdef.disabled_redirection, formdef.name)
979 c2ffbce0 Frédéric Péters
                '</li>\n'
980 1eaca06e Thomas Noël
            if len(formdefs) < limit:
981
                for formdef in formdefs_advertise[:limit-len(formdefs)]:
982
                    '<li>'
983
                    '<a href="%s/%s/">%s</a>' % (category.url_name, formdef.url_name, formdef.name)
984
                    ' (%s)' % _('authentication required')
985
                    '</li>\n'
986
            if (len(formdefs)+len(formdefs_advertise)) > limit:
987 c0ef273e Frédéric Péters
                '<li class="all-forms"><a href="%s/" title="%s">%s</a></li>' % (category.url_name,
988
                        _('Access to all forms of the "%s" category') % category.name,
989 dafd955b Frédéric Péters
                        _('Access to all forms in this category'))
990 c2ffbce0 Frédéric Péters
            '</ul>'
991
            '</li>\n'
992 05c98e5f Frédéric Péters
993 b08ecb38 Frédéric Péters
    def consultations [html] (self):
994 aeda4490 Frédéric Péters
        cats = [x for x in Category.select() if x.url_name == 'consultations']
995
        if not cats:
996
            return
997
        consultations_category = cats[0]
998
        formdefs = FormDef.select(lambda x: (
999 5f20613a Thomas Noël
                    x.category_id == consultations_category.id and
1000
                        (not x.disabled or x.disabled_redirection)),
1001 aeda4490 Frédéric Péters
                    order_by = 'name')
1002
        if not formdefs:
1003 cc5eac8c Frédéric Péters
            return
1004 05c98e5f Frédéric Péters
        ## Consultations
1005
        '<div id="consultations">'
1006
        '<h3>%s</h3>' % _('Consultations')
1007 aeda4490 Frédéric Péters
        if consultations_category.description:
1008
            '<p>'
1009
            consultations_category.description
1010
            '</p>'
1011 05c98e5f Frédéric Péters
        '<ul>'
1012
        for formdef in formdefs:
1013
            '<li>'
1014 5f20613a Thomas Noël
            if not formdef.disabled:
1015
                '<a href="%s/%s/">%s</a>' % (consultations_category.url_name,
1016
                    formdef.url_name, formdef.name)
1017
            else: # redirection
1018
                '<a href="%s">%s</a>' % (formdef.disabled_redirection, formdef.name)
1019 05c98e5f Frédéric Péters
            '</li>'
1020
        '</ul>'
1021
        '</div>'
1022
1023 eb24b1dd Frédéric Péters
    def box_side [html] (self, path):
1024 07975eba Frédéric Péters
        '<div id="sidebox">'
1025 5374ecec Frédéric Péters
        root_url = get_publisher().get_root_url()
1026
1027
        if self.has_anonymous_access_codes():
1028
            '<form id="follow-form" action="%saccesscode">' % root_url
1029
            '<h3>%s</h3>' % _('Tracking')
1030
            '<label>%s</label> ' % _('Code:')
1031
            '<input name="code" size="10"/>'
1032
            '</form>'
1033
1034 07975eba Frédéric Péters
        self.links()
1035 aeda4490 Frédéric Péters
1036
        cats = Category.select(order_by = 'name')
1037 818bc7c2 Frédéric Péters
        cats = [x for x in cats if x.url_name != 'consultations' and x.get_homepage_position() == 'side']
1038 aeda4490 Frédéric Péters
        Category.sort_by_position(cats)
1039
        if cats:
1040
            '<div id="side-services">'
1041
            '<h3>%s</h3>' % _('Services')
1042
            '<ul>'
1043
            for cat in cats:
1044
                '<li><a href="%s/">%s</a></li>' % (cat.url_name, cat.name)
1045
            '</ul>'
1046
            '</div>'
1047
1048 07975eba Frédéric Péters
        if Event.keys(): # if there are events, add a link to the agenda
1049 42f50eae Frédéric Péters
            tags = get_cfg('misc', {}).get('event_tags')
1050
            if not tags:
1051 a11cfbfc Frédéric Péters
                tags = get_default_event_tags()
1052 8097c060 Frédéric Péters
            '<h3 id="agenda-link"><a href="%sagenda/">%s</a></h3>' % (root_url, _('Agenda'))
1053 0e37c81a Frédéric Péters
1054 eb24b1dd Frédéric Péters
            if path and path[0] == 'agenda':
1055 0e37c81a Frédéric Péters
                '<p class="tags">'
1056
                for tag in tags:
1057
                    '<a href="%sagenda/tag/%s">%s</a> ' % (root_url, tag, tag)
1058
                '</p>'
1059 eb24b1dd Frédéric Péters
                self.agenda.display_remote_calendars()
1060 f62325ef Frédéric Péters
1061 0e37c81a Frédéric Péters
                '<p>'
1062
                '  <a href="%sagenda/filter">%s</a>' % (root_url, _('Advanced Filter'))
1063
                '</p>'
1064 c6ebe114 Frédéric Péters
1065 07975eba Frédéric Péters
        '</div>'
1066
1067 5374ecec Frédéric Péters
    def has_anonymous_access_codes(self):
1068
        for workflow in Workflow.select():
1069
            for wfstatus in workflow.possible_status:
1070
                for wfitem in wfstatus.items:
1071
                    if wfitem.key == 'create-anonymous-access-code':
1072
                        return True
1073
        return False
1074
1075
    def accesscode(self):
1076
        code = get_request().form.get('code')
1077
        if not code:
1078
            return redirect(get_publisher().get_root_url())
1079
        try:
1080
            token = Token.get(code)
1081
        except KeyError:
1082
            return redirect(get_publisher().get_root_url())
1083
        if token.type != 'anonymous-access-code':
1084
            return redirect(get_publisher().get_root_url())
1085
        formdef_urlname, formdata_id = token.formdata_reference
1086
        try:
1087
            formdata = FormDef.get_by_urlname(formdef_urlname).data_class().get(formdata_id)
1088
        except KeyError:
1089
            return redirect(get_publisher().get_root_url())
1090
        session = get_session()
1091
        if not hasattr(session, '_wf_anonymous_access_authorized'):
1092
            session._wf_anonymous_access_authorized = []
1093
        session._wf_anonymous_access_authorized.append(formdata.get_url())
1094
        return redirect(formdata.get_url() + 'access/')
1095 07975eba Frédéric Péters
1096 b08ecb38 Frédéric Péters
    def links [html] (self):
1097 3be7cfa9 Frédéric Péters
        links = Link.select()
1098 e2c667b9 Frédéric Péters
        if not links:
1099
            return
1100
1101 3be7cfa9 Frédéric Péters
        Link.sort_by_position(links)
1102 772d3287 Frédéric Péters
1103
        '<div id="links">'
1104 6eb2aab4 Frédéric Péters
        if links[0].url:
1105
            # first link has an URL, so it's not a title, so we display a
1106
            # generic title
1107
            '<h3>%s</h3>' % _('Useful links')
1108
        has_ul = False
1109 772d3287 Frédéric Péters
        for link in links:
1110 6eb2aab4 Frédéric Péters
            if not link.url:
1111
                # acting title
1112
                if has_ul:
1113
                    '</ul>'
1114
                '<h3>%s</h3>' % link.title
1115
                '<ul>'
1116
                has_ul = True
1117
            else:
1118
                if not has_ul:
1119
                    '<ul>'
1120
                    has_ul = True
1121
                '<li><a href="%s">%s</a></li>' % (link.url, link.title)
1122
        if has_ul:
1123
            '</ul>'
1124 772d3287 Frédéric Péters
        '</div>'
1125 05c98e5f Frédéric Péters
1126 b08ecb38 Frédéric Péters
1127
    def announces [html] (self):
1128 7038bf81 Frédéric Péters
        announces = Announce.get_published_announces()
1129 e2c667b9 Frédéric Péters
        if not announces:
1130
            return
1131
1132
        '<div id="announces">'
1133
        '<h3>%s</h3>' % _('Announces to citizens')
1134 3befb855 Frédéric Péters
        for item in announces[:3]:
1135 e2c667b9 Frédéric Péters
            '<div class="announce-item">'
1136
            '<h4>'
1137 cd827b62 Frédéric Péters
            if item.publication_time:
1138 7038bf81 Frédéric Péters
                time.strftime(misc.date_format(), item.publication_time)
1139 cd827b62 Frédéric Péters
                ' - '
1140 e2c667b9 Frédéric Péters
            item.title
1141
            '</h4>'
1142
            '<p>'
1143
            item.text
1144 32ba0ff4 Frédéric Péters
            '</p>'
1145
            '</div>'
1146 05c98e5f Frédéric Péters
1147 8d66bd48 Frédéric Péters
        '<ul id="announces-links">'
1148
        '<li><a href="announces/subscribe">%s</a></li>' % _('Receiving those Announces')
1149
        '<li><a href="announces/">%s</a></li>' % _('Previous Announces')
1150
        '</ul>'
1151 e2c667b9 Frédéric Péters
        '</div>'
1152
1153 6122f5dc Frédéric Péters
    def myspace_snippet [html] (self):
1154
        '<div id="myspace">'
1155
        '<h3>%s</h3>' % _('My Space')
1156
        '<ul>'
1157 0c7d90c5 Frédéric Péters
        if get_request().user and not get_request().user.anonymous:
1158
            '  <li><a href="myspace/" id="member">%s</a></li>' % _('Access to your personal space')
1159
            '  <li><a href="logout" id="logout">%s</a></li>' % _('Logout')
1160
        else:
1161
            '  <li><a href="register/" id="inscr">%s</a></li>' % _('Registration')
1162
            '  <li><a href="login/" id="login">%s</a></li>' % _('Login')
1163 6122f5dc Frédéric Péters
        '</ul>'
1164
        '</div>'
1165
1166
1167 26c0cfe4 Frédéric Péters
    def page_view [html] (self, key, title, urlname = None):
1168
        if not urlname:
1169
            urlname = key[3:].replace(str('_'), str('-'))
1170
        get_response().breadcrumb.append((urlname, title))
1171 32ba0ff4 Frédéric Péters
        template.html_top(title)
1172 26c0cfe4 Frédéric Péters
        '<div class="article">'
1173
        htmltext(TextsDirectory.get_html_text(key))
1174
        '</div>'
1175 4ee9f1b4 Frédéric Péters
1176 32ba0ff4 Frédéric Péters
    def informations_editeur [html] (self):
1177 b7a2808c Frédéric Péters
        get_response().filter['bigdiv'] = 'info'
1178 26c0cfe4 Frédéric Péters
        return self.page_view('aq-editor-info', _('Editor Informations'),
1179
                urlname = 'informations_editeur')
1180 32ba0ff4 Frédéric Péters
1181
    def accessibility(self):
1182 b7a2808c Frédéric Péters
        get_response().filter['bigdiv'] = 'accessibility'
1183 26c0cfe4 Frédéric Péters
        return self.page_view('aq-accessibility', _('Accessibility Statement'))
1184 32ba0ff4 Frédéric Péters
1185 0e0fb1de Frédéric Péters
    def contact(self):
1186 b7a2808c Frédéric Péters
        get_response().filter['bigdiv'] = 'contact'
1187 26c0cfe4 Frédéric Péters
        return self.page_view('aq-contact', _('Contact'))
1188 0e0fb1de Frédéric Péters
1189 32ba0ff4 Frédéric Péters
    def help(self):
1190 b7a2808c Frédéric Péters
        get_response().filter['bigdiv'] = 'help'
1191 26c0cfe4 Frédéric Péters
        return self.page_view('aq-help', _('Help'))
1192 b7a2808c Frédéric Péters
1193 05c98e5f Frédéric Péters
1194 38f6e2aa Frédéric Péters
from qommon.publisher import get_publisher_class
1195 b1c812cb Frédéric Péters
get_publisher_class().root_directory_class = AlternateRootDirectory
1196 69e8d81d Frédéric Péters
get_publisher_class().after_login_url = 'myspace/'
1197 04000f05 Frédéric Péters
get_publisher_class().use_sms_feature = True
1198 8efa60ca Frédéric Péters
1199
1200
EmailsDirectory.register('announces-subscription-confirmation',
1201
        N_('Confirmation of Announces Subscription'),
1202 89274e51 Frédéric Péters
        N_('Available variables: change_url, cancel_url, time, sitename'),
1203
        default_subject = N_('Announce Subscription Request'),
1204
        default_body = N_("""\
1205
You have (or someone impersonating you has) requested to subscribe to
1206
announces from [sitename].  To confirm this request, visit the
1207
following link:
1208
1209
[confirm_url]
1210
1211
If you are not the person who made this request, or you wish to cancel
1212
this request, visit the following link:
1213
1214
[cancel_url]
1215
1216
If you do nothing, the request will lapse after 3 days (precisely on
1217
[time]).
1218
"""))
1219 8efa60ca Frédéric Péters
1220 2d29ba83 Frédéric Péters
1221
TextsDirectory.register('aq-announces-subscription',
1222 89274e51 Frédéric Péters
        N_('Text on announces subscription page'),
1223
        default = N_('''\
1224
<p>
1225
FIXME
1226
'</p>'''))
1227 2d29ba83 Frédéric Péters
1228 68f47a3e Frédéric Péters
TextsDirectory.register('aq-sms-demo',
1229 89274e51 Frédéric Péters
        N_('Text when subscribing to announces SMS and configured as demo'),
1230
        default = N_('''
1231
<p>
1232
Receiving announces by SMS is not possible in this demo
1233
</p>'''))
1234 68f47a3e Frédéric Péters
1235 26c0cfe4 Frédéric Péters
TextsDirectory.register('aq-editor-info', N_('Editor Informations'))
1236
TextsDirectory.register('aq-accessibility', N_('Accessibility Statement'))
1237
TextsDirectory.register('aq-contact', N_('Contact Information'))
1238
TextsDirectory.register('aq-help', N_('Help'))
1239 e5c0a39d Frédéric Péters
TextsDirectory.register('aq-sso-text',  N_('Connecting with Identity Provider'),
1240
        default = N_('''<h3>Connecting with Identity Provider</h3>
1241
<p>You can also use your identity provider to connect.
1242
</p>'''))
1243 0009f81f Frédéric Péters
1244 00f76b53 Frédéric Péters
TextsDirectory.register('aq-home-page', N_('Home Page'), wysiwyg = True)