Projet

Général

Profil

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

root / extra / modules / myspace.py @ c182b1ab

1
try:
2
    import lasso
3
except ImportError:
4
    pass
5

    
6
import json
7

    
8
from quixote import get_publisher, get_request, redirect, get_response, get_session_manager, get_session
9
from quixote.directory import AccessControlled, Directory
10
from quixote.html import TemplateIO, htmltext
11
from quixote.util import StaticFile, FileStream
12

    
13
from qommon import template
14
from qommon.form import *
15
from qommon import get_cfg, get_logger
16
from qommon import errors
17
from wcs.api import get_user_from_api_query_string
18

    
19
import qommon.ident.password
20
from qommon.ident.password_accounts import PasswordAccount
21

    
22
from qommon.admin.texts import TextsDirectory
23

    
24
from wcs.formdef import FormDef
25
import wcs.myspace
26
import root
27

    
28
from announces import AnnounceSubscription
29
from strongbox import StrongboxItem, StrongboxType
30
from payments import Invoice, Regie, is_payment_supported
31
import msp_ui
32

    
33
class MyInvoicesDirectory(Directory):
34
    _q_exports = ['']
35

    
36
    def _q_traverse(self, path):
37
        if not is_payment_supported():
38
            raise errors.TraversalError()
39
        get_response().breadcrumb.append(('invoices/', _('Invoices')))
40
        return Directory._q_traverse(self, path)
41

    
42
    def _q_index(self):
43
        user = get_request().user
44
        if not user or user.anonymous:
45
            raise errors.AccessUnauthorizedError()
46

    
47
        template.html_top(_('Invoices'))
48
        r = TemplateIO(html=True)
49
        r += TextsDirectory.get_html_text('aq-myspace-invoice')
50

    
51
        r += get_session().display_message()
52

    
53
        invoices = []
54
        invoices.extend(Invoice.get_with_indexed_value(
55
            str('user_id'), str(user.id)))
56
        try:
57
            invoices.extend(Invoice.get_with_indexed_value(
58
                str('user_hash'), str(user.hash)))
59
        except AttributeError:
60
            pass
61

    
62
        def cmp_invoice(a, b):
63
            t = cmp(a.regie_id, b.regie_id)
64
            if t != 0:
65
                return t
66
            return -cmp(a.date, b.date)
67

    
68
        invoices.sort(cmp_invoice)
69

    
70
        last_regie_id = None
71
        unpaid = False
72
        for invoice in invoices:
73
            if invoice.regie_id != last_regie_id:
74
                if last_regie_id:
75
                    r += htmltext('</ul>')
76
                    if unpaid:
77
                        r += htmltext('<input type="submit" value="%s"/>') % _('Pay Selected Invoices')
78
                    r += htmltext('</form>')
79
                last_regie_id = invoice.regie_id
80
                r += htmltext('<h3>%s</h3>') % Regie.get(last_regie_id).label
81
                unpaid = False
82
                r += htmltext('<form action="%s/invoices/multiple">' % get_publisher().get_frontoffice_url())
83
                r += htmltext('<ul>')
84

    
85
            r += htmltext('<li>')
86
            if not (invoice.paid or invoice.canceled):
87
                r += htmltext('<input type="checkbox" name="invoice" value="%s"/>' % invoice.id)
88
                unpaid = True
89
            r += misc.localstrftime(invoice.date)
90
            r += ' - '
91
            r += '%s' % invoice.subject
92
            r += ' - '
93
            r += '%s' % invoice.amount
94
            r += htmltext(' &euro;')
95
            r += ' - '
96
            button = '<span class="paybutton">%s</span>' % _('Pay')
97
            if invoice.canceled:
98
                r += _('canceled on %s') % misc.localstrftime(invoice.canceled_date)
99
                r += ' - '
100
                button = _('Details')
101
            if invoice.paid:
102
                r += _('paid on %s') % misc.localstrftime(invoice.paid_date)
103
                r += ' - '
104
                button = _('Details')
105
            r += htmltext('<a href="%s/invoices/%s">%s</a>' % (get_publisher().get_frontoffice_url(),
106
                    invoice.id, button))
107
            r += htmltext('</li>')
108

    
109
        if last_regie_id:
110
            r += htmltext('</ul>')
111
            if unpaid:
112
                r += htmltext('<input type="submit" value="%s"/>') % _('Pay Selected Invoices')
113
            r += htmltext('</form>')
114

    
115
        return r.getvalue()
116

    
117

    
118
class StrongboxDirectory(Directory):
119
    _q_exports = ['', 'add', 'download', 'remove', 'pick', 'validate']
120

    
121
    def _q_traverse(self, path):
122
        if not get_cfg('misc', {}).get('aq-strongbox'):
123
            raise errors.TraversalError()
124
        get_response().breadcrumb.append(('strongbox/', _('Strongbox')))
125
        return Directory._q_traverse(self, path)
126

    
127
    def get_form(self):
128
        types = [(x.id, x.label) for x in StrongboxType.select()]
129
        form = Form(action='add', enctype='multipart/form-data')
130
        form.add(StringWidget, 'description', title=_('Description'), size=60)
131
        form.add(FileWidget, 'file', title=_('File'), required=True)
132
        form.add(SingleSelectWidget, 'type_id', title=_('Document Type'),
133
                 options = [(None, _('Not specified'))] + types)
134
        form.add(DateWidget, 'date_time', title = _('Document Date'))
135
        form.add_submit('submit', _('Upload'))
136
        return form
137

    
138
    def _q_index(self):
139
        template.html_top(_('Strongbox'))
140
        r = TemplateIO(html=True)
141

    
142
        # TODO: a paragraph of explanations here could be useful
143

    
144
        sffiles = StrongboxItem.get_with_indexed_value(
145
                        str('user_id'), str(get_request().user.id))
146
        if sffiles:
147
            r += htmltext('<table id="strongbox-items">')
148
            r += htmltext('<tr><th></th><th>%s</th><th>%s</th><th></th></tr>') % (
149
                _('Type'), _('Expiration'))
150
        else:
151
            r += htmltext('<p>')
152
            r += _('There is currently nothing in your strongbox.')
153
            r += htmltext('</p>')
154
        has_items_to_validate = False
155
        for i, sffile in enumerate(sffiles):
156
            expired = False
157
            if not sffile.validated_time:
158
                has_items_to_validate = True
159
                continue
160
            if sffile.expiration_time and sffile.expiration_time < time.localtime():
161
                expired = True
162
            if i%2:
163
                classnames = ['odd']
164
            else:
165
                classnames = ['even']
166
            if expired:
167
                classnames.append('expired')
168
            r += htmltext('<tr class="%s">') % ' '.join(classnames)
169
            r += htmltext('<td class="label">')
170
            r += sffile.get_display_name()
171
            r += htmltext('</td>')
172
            if sffile.type_id:
173
                r += htmltext('<td class="type">%s</td>') % StrongboxType.get(sffile.type_id).label
174
            else:
175
                r += htmltext('<td class="type">-</td>')
176
            if sffile.expiration_time:
177
                r += htmltext('<td class="expiration">%s') % strftime(misc.date_format(), sffile.expiration_time)
178
                if expired:
179
                    r += ' (%s)' % _('expired')
180
                r += htmltext('</td>')
181
            else:
182
                r += htmltext('<td class="expiration">-</td>')
183
            r += htmltext('<td class="actions">')
184
            r += htmltext(' [<a href="download?id=%s">%s</a>] ') % (sffile.id, _('download'))
185
            r += htmltext('[<a rel="popup" href="remove?id=%s">%s</a>] ') % (sffile.id, _('remove'))
186
            r += htmltext('</td>')
187
            r += htmltext('</tr>')
188

    
189
        if has_items_to_validate:
190
            r += htmltext('<tr><td colspan="4"><h3>%s</h3></td></tr>') % _('Proposed Items')
191
            for sffile in sffiles:
192
                if sffile.validated_time:
193
                    continue
194
                if sffile.expiration_time and sffile.expiration_time < time.localtime():
195
                    expired = True
196
                if i%2:
197
                    classnames = ['odd']
198
                else:
199
                    classnames = ['even']
200
                if expired:
201
                    classnames.append('expired')
202
                r += htmltext('<tr class="%s">') % ' '.join(classnames)
203

    
204
                r += htmltext('<td class="label">')
205
                r += sffile.get_display_name()
206
                r += htmltext('</td>')
207
                if sffile.type_id:
208
                    r += htmltext('<td class="type">%s</td>') % StrongboxType.get(sffile.type_id).label
209
                else:
210
                    r += htmltext('<td class="type">-</td>')
211

    
212
                if sffile.expiration_time:
213
                    r += htmltext('<td class="expiration">%s') % strftime(misc.date_format(), sffile.expiration_time)
214
                    if expired:
215
                        r += ' (%s)' % _('expired')
216
                    r += htmltext('</td>')
217
                else:
218
                    r += htmltext('<td class="expiration">-</td>')
219
                r += htmltext('<td class="actions">')
220
                r += htmltext(' [<a href="download?id=%s">%s</a>] ') % (sffile.id, _('download'))
221
                r += htmltext(' [<a href="validate?id=%s">%s</a>] ') % (sffile.id, _('validate'))
222
                r += htmltext(' [<a href="remove?id=%s">%s</a>] ') % (sffile.id, _('reject'))
223
                r += htmltext('</td>')
224
                r += htmltext('</tr>')
225
        if sffiles:
226
            r += htmltext('</table>')
227

    
228
        r += htmltext('<h3>%s</h3>') % _('Add a file to the strongbox')
229
        form = self.get_form()
230
        r += form.render()
231
        return r.getvalue()
232

    
233
    def add(self):
234
        form = self.get_form()
235
        if not form.is_submitted():
236
            if get_request().form.get('mode') == 'pick':
237
                return redirect('pick')
238
            else:
239
                return redirect('.')
240

    
241
        sffile = StrongboxItem()
242
        sffile.user_id = get_request().user.id
243
        sffile.description = form.get_widget('description').parse()
244
        sffile.validated_time = time.localtime()
245
        sffile.type_id = form.get_widget('type_id').parse()
246
        v = form.get_widget('date_time').parse()
247
        sffile.set_expiration_time_from_date(v)
248
        sffile.store()
249
        sffile.set_file(form.get_widget('file').parse())
250
        sffile.store()
251
        if get_request().form.get('mode') == 'pick':
252
            return redirect('pick')
253
        else:
254
            return redirect('.')
255

    
256
    def download(self):
257
        id = get_request().form.get('id')
258
        if not id:
259
            raise errors.TraversalError()
260
        try:
261
            sffile = StrongboxItem.get(id)
262
        except KeyError:
263
            raise errors.TraversalError()
264
        if str(sffile.user_id) != str(get_request().user.id):
265
            raise errors.TraversalError()
266

    
267
        filename = sffile.file.filename
268
        fd = file(filename)
269
        size = os.path.getsize(filename)
270
        response = get_response()
271
        response.set_content_type('application/octet-stream')
272
        response.set_header('content-disposition', 'attachment; filename="%s"' % sffile.file.base_filename)
273
        return FileStream(fd, size)
274

    
275
    def validate(self):
276
        id = get_request().form.get('id')
277
        if not id:
278
            raise errors.TraversalError()
279
        try:
280
            sffile = StrongboxItem.get(id)
281
        except KeyError:
282
            raise errors.TraversalError()
283
        if str(sffile.user_id) != str(get_request().user.id):
284
            raise errors.TraversalError()
285
        sffile.validated_time = time.time()
286
        sffile.store()
287
        return redirect('.')
288

    
289
    def remove(self):
290
        id = get_request().form.get('id')
291
        if not id:
292
            raise errors.TraversalError()
293
        try:
294
            sffile = StrongboxItem.get(id)
295
        except KeyError:
296
            raise errors.TraversalError()
297
        if str(sffile.user_id) != str(get_request().user.id):
298
            raise errors.TraversalError()
299

    
300
        r = TemplateIO(html=True)
301
        form = Form(enctype='multipart/form-data')
302
        form.add_hidden('id', get_request().form.get('id'))
303
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
304
                        'You are about to irrevocably delete this item from your strongbox.')))
305
        form.add_submit('submit', _('Submit'))
306
        form.add_submit('cancel', _('Cancel'))
307
        if form.get_submit() == 'cancel':
308
            return redirect('.')
309
        if not form.is_submitted() or form.has_errors():
310
            if sffile.type_id:
311
                r += htmltext('<h2>%s</h2>') % _('Deleting %(filetype)s: %(filename)s') % {
312
                        'filetype': StrongboxType.get(sffile.type_id).label,
313
                        'filename': sffile.get_display_name()
314
                    }
315
            else:
316
                r += htmltext('<h2>%s</h2>') % _('Deleting %(filename)s') % {'filename': sffile.get_display_name()}
317
            r += form.render()
318
            return r.getvalue()
319
        else:
320
            sffile.remove_self()
321
            sffile.remove_file()
322
            return redirect('.')
323

    
324
    def picked_file(self):
325
        get_response().set_content_type('application/json')
326
        sffile = StrongboxItem.get(get_request().form.get('val'))
327
        sffile.file.fp = file(sffile.file.filename)
328
        if sffile.user_id != get_request().user.id:
329
            raise errors.TraversalError()
330
        # XXX: this will copy the file, it would be quite nice if it was
331
        # possible to just make it a symlink to the sffile
332
        token = get_session().add_tempfile(sffile.file)
333
        return json.dumps({'token': token, 'filename': sffile.file.base_filename})
334

    
335
    def pick(self):
336
        if get_request().form.get('select') == 'true':
337
            return self.picked_file()
338
        r = TemplateIO(html=True)
339
        root_url = get_publisher().get_root_url()
340
        sffiles = StrongboxItem.get_with_indexed_value(
341
                        str('user_id'), str(get_request().user.id))
342
        r += htmltext('<h2>%s</h2>') % _('Pick a file')
343

    
344
        if not sffiles:
345
            r += htmltext('<p>')
346
            r += _('You do not have any file in your strongbox at the moment.')
347
            r += htmltext('</p>')
348
            r += htmltext('<div class="buttons">')
349
            r += htmltext('<a href="%smyspace/strongbox/" target="_blank">%s</a>') % (root_url,
350
                _('Open Strongbox Management'))
351
            r += htmltext('</div>')
352
        else:
353
            r += htmltext('<form id="strongbox-pick">')
354
            r += htmltext('<ul>')
355
            for sffile in sffiles:
356
                r += htmltext('<li><label><input type="radio" name="file" value="%s"/>%s</label>') % (
357
                                sffile.id, sffile.get_display_name())
358
                r += htmltext(' [<a href="%smyspace/strongbox/download?id=%s">%s</a>] ') % (
359
                                root_url, sffile.id, _('view'))
360
                r += htmltext('</li>')
361
            r += htmltext('</ul>')
362

    
363
            r += htmltext('<div class="buttons">')
364
            r += htmltext('<input name="cancel" type="button" value="%s"/>') % _('Cancel')
365
            r += ' '
366
            r += htmltext('<input name="pick" type="button" value="%s"/>') % _('Pick')
367
            r += htmltext('</div>')
368
            r += htmltext('</form>')
369
        return r.getvalue()
370

    
371

    
372
class JsonDirectory(Directory):
373
    '''Export of several lists in json, related to the current user or the
374
       SAMLv2 NameID we'd get in the URL'''
375

    
376
    _q_exports = ['forms']
377

    
378
    user = None
379

    
380
    def _q_traverse(self, path):
381
        self.user = get_user_from_api_query_string() or get_request().user
382
        if not self.user:
383
            raise errors.AccessUnauthorizedError()
384
        return Directory._q_traverse(self, path)
385

    
386
    def forms(self):
387
        formdefs = FormDef.select(lambda x: not x.is_disabled(), order_by = 'name')
388
        user_forms = []
389
        for formdef in formdefs:
390
            user_forms.extend(formdef.data_class().get_with_indexed_value(
391
                        'user_id', self.user.id))
392
            try:
393
                user_forms.extend(formdef.data_class().get_with_indexed_value(
394
                        'user_hash', self.user.hash))
395
            except AttributeError:
396
                pass
397
        user_forms.sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
398

    
399
        get_response().set_content_type('application/json')
400

    
401

    
402
        forms_output = []
403
        for form in user_forms:
404
            visible_status = form.get_visible_status(user=self.user)
405
            # skip hidden forms
406
            if not visible_status:
407
                continue
408
            name = form.formdef.name
409
            id = form.get_display_id()
410
            status = visible_status.name
411
            title = _('%(name)s #%(id)s (%(status)s)') % {
412
                    'name': name,
413
                    'id': id,
414
                    'status': status
415
            }
416
            url = form.get_url()
417
            d = { 'title': title, 'url': url }
418
            d.update(form.get_substitution_variables(minimal=True))
419
            forms_output.append(d)
420
        return json.dumps(forms_output)
421

    
422

    
423
class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
424
    _q_exports = ['', 'profile', 'new', 'password', 'remove', 'drafts', 'forms',
425
            'announces', 'strongbox', 'invoices', 'json', 'msp']
426

    
427
    msp = msp_ui.MSPDirectory()
428
    strongbox = StrongboxDirectory()
429
    invoices = MyInvoicesDirectory()
430
    json = JsonDirectory()
431

    
432
    def _q_traverse(self, path):
433
        get_response().filter['bigdiv'] = 'profile'
434
        get_response().breadcrumb.append(('myspace/', _('My Space')))
435

    
436
        # Migrate custom text settings
437
        texts_cfg = get_cfg('texts', {})
438
        if 'text-aq-top-of-profile' in texts_cfg and (
439
                        not 'text-top-of-profile' in texts_cfg):
440
            texts_cfg['text-top-of-profile'] = texts_cfg['text-aq-top-of-profile']
441
            del texts_cfg['text-aq-top-of-profile']
442
            get_publisher().write_cfg()
443

    
444
        return Directory._q_traverse(self, path)
445

    
446

    
447
    def _q_index(self):
448
        user = get_request().user
449
        if not user:
450
            raise errors.AccessUnauthorizedError()
451
        template.html_top(_('My Space'))
452
        r = TemplateIO(html=True)
453
        if user.anonymous:
454
            return redirect('new')
455

    
456
        user_formdef = user.get_formdef()
457

    
458
        user_forms = []
459
        if user:
460
            formdefs = FormDef.select(lambda x: not x.is_disabled(), order_by = 'name')
461
            user_forms = []
462
            for formdef in formdefs:
463
                user_forms.extend(formdef.data_class().get_with_indexed_value(
464
                            'user_id', user.id))
465
                try:
466
                    user_forms.extend(formdef.data_class().get_with_indexed_value(
467
                            'user_hash', user.hash))
468
                except AttributeError:
469
                    pass
470
            user_forms.sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
471

    
472
        profile_links = []
473
        if not get_cfg('sp', {}).get('idp-manage-user-attributes', False):
474
            if user_formdef:
475
                profile_links.append('<a href="#my-profile">%s</a>' % _('My Profile'))
476
        if user_forms:
477
            profile_links.append('<a href="#my-forms">%s</a>' % _('My Forms'))
478
        if get_cfg('misc', {}).get('aq-strongbox'):
479
            profile_links.append('<a href="strongbox/">%s</a>' % _('My Strongbox'))
480
        if is_payment_supported():
481
            profile_links.append('<a href="invoices/">%s</a>' % _('My Invoices'))
482

    
483
        root_url = get_publisher().get_root_url()
484
        if user.can_go_in_backoffice():
485
            profile_links.append('<a href="%sbackoffice/">%s</a>' % (root_url, _('Back office')))
486
        if user.is_admin:
487
            profile_links.append('<a href="%sadmin/">%s</a>' % (root_url, _('Admin')))
488

    
489
        if profile_links:
490
            r += htmltext('<p id="profile-links">')
491
            r += htmltext(' - '.join(profile_links))
492
            r += htmltext('</p>')
493

    
494
        if not get_cfg('sp', {}).get('idp-manage-user-attributes', False):
495
            if user_formdef:
496
                r += self._my_profile(user_formdef, user)
497

    
498
            r += self._index_buttons(user_formdef)
499

    
500
            try:
501
                x = PasswordAccount.get_on_index(get_request().user.id, str('user_id'))
502
            except KeyError:
503
                pass
504
            else:
505
                r += htmltext('<p>')
506
                r += _('You can delete your account freely from the services portal. '
507
                       'This action is irreversible; it will destruct your personal '
508
                       'datas and destruct the access to your request history.')
509
                r += htmltext(' <strong><a href="remove" rel="popup">%s</a></strong>.') % _('Delete My Account')
510
                r += htmltext('</p>')
511

    
512
        options = get_cfg('misc', {}).get('announce_themes')
513
        if options:
514
            try:
515
                subscription = AnnounceSubscription.get_on_index(
516
                        get_request().user.id, str('user_id'))
517
            except KeyError:
518
                pass
519
            else:
520
                r += htmltext('<p class="command"><a href="announces">%s</a></p>') % _(
521
                        'Edit my Subscription to Announces')
522

    
523
        if user_forms:
524
            r += htmltext('<h3 id="my-forms">%s</h3>') % _('My Forms')
525
            r += root.FormsRootDirectory().user_forms(user_forms)
526

    
527
        return r.getvalue()
528

    
529
    def _my_profile(self, user_formdef, user):
530
        r = TemplateIO(html=True)
531
        r += htmltext('<h3 id="my-profile">%s</h3>') % _('My Profile')
532

    
533
        r += TextsDirectory.get_html_text('top-of-profile')
534

    
535
        if user.form_data:
536
            r += htmltext('<ul>')
537
            for field in user_formdef.fields:
538
                if not hasattr(field, str('get_view_value')):
539
                    continue
540
                value = user.form_data.get(field.id)
541
                r += htmltext('<li>')
542
                r += field.label
543
                r += ' : '
544
                if value:
545
                    r += field.get_view_value(value)
546
                r += htmltext('</li>')
547
            r += htmltext('</ul>')
548
        else:
549
            r += htmltext('<p>%s</p>') % _('Empty profile')
550
        return r.getvalue()
551

    
552
    def _index_buttons(self, form_data):
553
        r = TemplateIO(html=True)
554
        passwords_cfg = get_cfg('passwords', {})
555
        ident_method = get_cfg('identification', {}).get('methods', ['idp'])[0]
556
        if get_session().lasso_session_dump:
557
            ident_method = 'idp'
558

    
559
        if form_data and ident_method != 'idp':
560
            r += htmltext('<p class="command"><a href="profile" rel="popup">%s</a></p>') % _('Edit My Profile')
561

    
562
        if ident_method == 'password' and passwords_cfg.get('can_change', False):
563
            r += htmltext('<p class="command"><a href="password" rel="popup">%s</a></p>') % _('Change My Password')
564

    
565
        return r.getvalue()
566

    
567
    def profile(self):
568
        user = get_request().user
569
        if not user or user.anonymous:
570
            raise errors.AccessUnauthorizedError()
571

    
572
        form = Form(enctype = 'multipart/form-data')
573
        formdef = user.get_formdef()
574
        formdef.add_fields_to_form(form, form_data = user.form_data)
575

    
576
        form.add_submit('submit', _('Apply Changes'))
577
        form.add_submit('cancel', _('Cancel'))
578

    
579
        if form.get_submit() == 'cancel':
580
            return redirect('.')
581

    
582
        if form.is_submitted() and not form.has_errors():
583
            self.profile_submit(form, formdef)
584
            return redirect('.')
585

    
586
        template.html_top(_('Edit Profile'))
587
        return form.render()
588

    
589
    def profile_submit(self, form, formdef):
590
        user = get_request().user
591
        data = formdef.get_data(form)
592

    
593
        user.set_attributes_from_formdata(data)
594
        user.form_data = data
595

    
596
        user.store()
597

    
598
    def password(self):
599
        ident_method = get_cfg('identification', {}).get('methods', ['idp'])[0]
600
        if ident_method != 'password':
601
            raise errors.TraversalError()
602

    
603
        user = get_request().user
604
        if not user or user.anonymous:
605
            raise errors.AccessUnauthorizedError()
606

    
607
        form = Form(enctype = 'multipart/form-data')
608
        form.add(PasswordWidget, 'new_password', title = _('New Password'),
609
                required=True)
610
        form.add(PasswordWidget, 'new2_password', title = _('New Password (confirm)'),
611
                required=True) 
612

    
613
        form.add_submit('submit', _('Change Password'))
614
        form.add_submit('cancel', _('Cancel'))
615

    
616
        if form.get_submit() == 'cancel':
617
            return redirect('.')
618

    
619
        if form.is_submitted() and not form.has_errors():
620
            qommon.ident.password.check_password(form, 'new_password')
621
            new_password = form.get_widget('new_password').parse()
622
            new2_password = form.get_widget('new2_password').parse()
623
            if new_password != new2_password:
624
                form.set_error('new2_password', _('Passwords do not match'))
625

    
626
        if form.is_submitted() and not form.has_errors():
627
            self.submit_password(new_password)
628
            return redirect('.')
629

    
630
        template.html_top(_('Change Password'))
631
        return form.render()
632

    
633
    def submit_password(self, new_password):
634
        passwords_cfg = get_cfg('passwords', {})
635
        account = PasswordAccount.get(get_session().username)
636
        account.hashing_algo = passwords_cfg.get('hashing_algo')
637
        account.set_password(new_password)
638
        account.store()
639

    
640
    def new(self):
641
        if not get_request().user or not get_request().user.anonymous:
642
            raise errors.AccessUnauthorizedError()
643

    
644
        form = Form(enctype = 'multipart/form-data')
645
        formdef = get_publisher().user_class.get_formdef()
646
        if formdef:
647
            formdef.add_fields_to_form(form)
648
        else:
649
            get_logger().error('missing user formdef (in myspace/new)')
650

    
651
        form.add_submit('submit', _('Register'))
652

    
653
        if form.is_submitted() and not form.has_errors():
654
            user = get_publisher().user_class()
655
            data = formdef.get_data(form)
656
            user.set_attributes_from_formdata(data)
657
            user.name_identifiers = get_request().user.name_identifiers
658
            user.lasso_dump = get_request().user.lasso_dump
659
            user.set_attributes_from_formdata(data)
660
            user.form_data = data
661
            user.store()
662
            get_session().set_user(user.id)
663
            root_url = get_publisher().get_root_url()
664
            return redirect('%smyspace' % root_url)
665

    
666
        template.html_top(_('Welcome'))
667
        return form.render()
668

    
669

    
670
    def remove(self):
671
        user = get_request().user
672
        if not user or user.anonymous:
673
            raise errors.AccessUnauthorizedError()
674

    
675
        form = Form(enctype = 'multipart/form-data')
676
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
677
                        'Are you really sure you want to remove your account?')))
678
        form.add_submit('submit', _('Remove my account'))
679
        form.add_submit('cancel', _('Cancel'))
680

    
681
        if form.get_submit() == 'cancel':
682
            return redirect('.')
683

    
684
        if form.is_submitted() and not form.has_errors():
685
            user = get_request().user
686
            account = PasswordAccount.get_on_index(user.id, str('user_id'))
687
            get_session_manager().expire_session() 
688
            account.remove_self()
689
            return redirect(get_publisher().get_root_url())
690

    
691
        template.html_top(_('Removing Account'))
692
        return form.render()
693

    
694
    def announces(self):
695
        options = get_cfg('misc', {}).get('announce_themes')
696
        if not options:
697
            raise errors.TraversalError()
698
        user = get_request().user
699
        if not user or user.anonymous:
700
            raise errors.AccessUnauthorizedError()
701
        subscription = AnnounceSubscription.get_on_index(get_request().user.id, str('user_id'))
702
        if not subscription:
703
            raise errors.TraversalError()
704

    
705
        if subscription.enabled_themes is None:
706
            enabled_themes = options
707
        else:
708
            enabled_themes = subscription.enabled_themes
709

    
710
        form = Form(enctype = 'multipart/form-data')
711
        form.add(CheckboxesWidget, 'themes', title=_('Announce Themes'),
712
                value=enabled_themes, elements=options,
713
                inline=False, required=False)
714

    
715
        form.add_submit('submit', _('Apply Changes'))
716
        form.add_submit('cancel', _('Cancel'))
717

    
718
        if form.get_submit() == 'cancel':
719
            return redirect('.')
720

    
721
        if form.is_submitted() and not form.has_errors():
722
            chosen_themes = form.get_widget('themes').parse()
723
            if chosen_themes == options:
724
                chosen_themes = None
725
            subscription.enabled_themes = chosen_themes
726
            subscription.store()
727
            return redirect('.')
728

    
729
        template.html_top()
730
        get_response().breadcrumb.append(('announces', _('Announce Subscription')))
731
        return form.render()
732

    
733

    
734
TextsDirectory.register('aq-myspace-invoice',
735
        N_('Message on top of invoices page'),
736
        category = N_('Invoices'))
737

    
(23-23/30)