Projet

Général

Profil

Télécharger (27,5 ko) Statistiques
| Branche: | Tag: | Révision:

root / auquotidien / modules / myspace.py @ 8b02623d

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 _
14
from qommon import template
15
from qommon.form import *
16
from qommon import get_cfg, get_logger
17
from qommon import errors
18
from wcs.api import get_user_from_api_query_string
19

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

    
23
from qommon.admin.texts import TextsDirectory
24

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

    
29
from announces import AnnounceSubscription
30
from strongbox import StrongboxItem, StrongboxType
31
from payments import Invoice, Regie, is_payment_supported
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

    
57
        def cmp_invoice(a, b):
58
            t = cmp(a.regie_id, b.regie_id)
59
            if t != 0:
60
                return t
61
            return -cmp(a.date, b.date)
62

    
63
        invoices.sort(cmp_invoice)
64

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

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

    
104
        if last_regie_id:
105
            r += htmltext('</ul>')
106
            if unpaid:
107
                r += htmltext('<input type="submit" value="%s"/>') % _('Pay Selected Invoices')
108
            r += htmltext('</form>')
109

    
110
        return r.getvalue()
111

    
112

    
113
class StrongboxDirectory(Directory):
114
    _q_exports = ['', 'add', 'download', 'remove', 'pick', 'validate']
115

    
116
    def _q_traverse(self, path):
117
        if not get_cfg('misc', {}).get('aq-strongbox'):
118
            raise errors.TraversalError()
119
        get_response().breadcrumb.append(('strongbox/', _('Strongbox')))
120
        return Directory._q_traverse(self, path)
121

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

    
133
    def _q_index(self):
134
        template.html_top(_('Strongbox'))
135
        r = TemplateIO(html=True)
136

    
137
        # TODO: a paragraph of explanations here could be useful
138

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

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

    
199
                r += htmltext('<td class="label">')
200
                r += sffile.get_display_name()
201
                r += htmltext('</td>')
202
                if sffile.type_id:
203
                    r += htmltext('<td class="type">%s</td>') % StrongboxType.get(sffile.type_id).label
204
                else:
205
                    r += htmltext('<td class="type">-</td>')
206

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

    
223
        r += htmltext('<h3>%s</h3>') % _('Add a file to the strongbox')
224
        form = self.get_form()
225
        r += form.render()
226
        return r.getvalue()
227

    
228
    def add(self):
229
        form = self.get_form()
230
        if not form.is_submitted():
231
            if get_request().form.get('mode') == 'pick':
232
                return redirect('pick')
233
            else:
234
                return redirect('.')
235

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

    
251
    def download(self):
252
        id = get_request().form.get('id')
253
        if not id:
254
            raise errors.TraversalError()
255
        try:
256
            sffile = StrongboxItem.get(id)
257
        except KeyError:
258
            raise errors.TraversalError()
259
        if str(sffile.user_id) != str(get_request().user.id):
260
            raise errors.TraversalError()
261

    
262
        filename = sffile.file.filename
263
        fd = file(filename)
264
        size = os.path.getsize(filename)
265
        response = get_response()
266
        response.set_content_type('application/octet-stream')
267
        response.set_header('content-disposition', 'attachment; filename="%s"' % sffile.file.base_filename)
268
        return FileStream(fd, size)
269

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

    
284
    def remove(self):
285
        id = get_request().form.get('id')
286
        if not id:
287
            raise errors.TraversalError()
288
        try:
289
            sffile = StrongboxItem.get(id)
290
        except KeyError:
291
            raise errors.TraversalError()
292
        if str(sffile.user_id) != str(get_request().user.id):
293
            raise errors.TraversalError()
294

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

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

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

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

    
358
            r += htmltext('<div class="buttons">')
359
            r += htmltext('<input name="cancel" type="button" value="%s"/>') % _('Cancel')
360
            r += ' '
361
            r += htmltext('<input name="pick" type="button" value="%s"/>') % _('Pick')
362
            r += htmltext('</div>')
363
            r += htmltext('</form>')
364
        return r.getvalue()
365

    
366

    
367
class JsonDirectory(Directory):
368
    '''Export of several lists in json, related to the current user or the
369
       SAMLv2 NameID we'd get in the URL'''
370

    
371
    _q_exports = ['forms']
372

    
373
    user = None
374

    
375
    def _q_traverse(self, path):
376
        self.user = get_user_from_api_query_string() or get_request().user
377
        if not self.user:
378
            raise errors.AccessUnauthorizedError()
379
        return Directory._q_traverse(self, path)
380

    
381
    def forms(self):
382
        formdefs = FormDef.select(order_by='name', ignore_errors=True)
383
        user_forms = []
384
        for formdef in formdefs:
385
            user_forms.extend(formdef.data_class().get_with_indexed_value(
386
                        'user_id', self.user.id))
387
        user_forms.sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
388

    
389
        get_response().set_content_type('application/json')
390

    
391

    
392
        forms_output = []
393
        for form in user_forms:
394
            visible_status = form.get_visible_status(user=self.user)
395
            # skip drafts and hidden forms
396
            if not visible_status:
397
                continue
398
            name = form.formdef.name
399
            id = form.get_display_id()
400
            status = visible_status.name
401
            title = _('%(name)s #%(id)s (%(status)s)') % {
402
                    'name': name,
403
                    'id': id,
404
                    'status': status
405
            }
406
            url = form.get_url()
407
            d = { 'title': title, 'url': url }
408
            d.update(form.get_substitution_variables(minimal=True))
409
            forms_output.append(d)
410
        return json.dumps(forms_output, cls=misc.JSONEncoder)
411

    
412

    
413
class MyspaceDirectory(wcs.myspace.MyspaceDirectory):
414
    _q_exports = ['', 'profile', 'new', 'password', 'remove', 'drafts', 'forms',
415
            'announces', 'strongbox', 'invoices', 'json']
416

    
417
    strongbox = StrongboxDirectory()
418
    invoices = MyInvoicesDirectory()
419
    json = JsonDirectory()
420

    
421
    def _q_traverse(self, path):
422
        get_response().filter['bigdiv'] = 'profile'
423
        get_response().breadcrumb.append(('myspace/', _('My Space')))
424

    
425
        # Migrate custom text settings
426
        texts_cfg = get_cfg('texts', {})
427
        if 'text-aq-top-of-profile' in texts_cfg and (
428
                        not 'text-top-of-profile' in texts_cfg):
429
            texts_cfg['text-top-of-profile'] = texts_cfg['text-aq-top-of-profile']
430
            del texts_cfg['text-aq-top-of-profile']
431
            get_publisher().write_cfg()
432

    
433
        return Directory._q_traverse(self, path)
434

    
435

    
436
    def _q_index(self):
437
        user = get_request().user
438
        if not user:
439
            raise errors.AccessUnauthorizedError()
440
        template.html_top(_('My Space'))
441
        r = TemplateIO(html=True)
442
        if user.anonymous:
443
            return redirect('new')
444

    
445
        user_formdef = user.get_formdef()
446

    
447
        user_forms = []
448
        if user:
449
            formdefs = FormDef.select(order_by='name', ignore_errors=True)
450
            user_forms = []
451
            for formdef in formdefs:
452
                user_forms.extend(formdef.data_class().get_with_indexed_value(
453
                            'user_id', user.id))
454
            user_forms.sort(lambda x,y: cmp(x.receipt_time, y.receipt_time))
455

    
456
        profile_links = []
457
        if not get_cfg('sp', {}).get('idp-manage-user-attributes', False):
458
            if user_formdef:
459
                profile_links.append('<a href="#my-profile">%s</a>' % _('My Profile'))
460
        if user_forms:
461
            profile_links.append('<a href="#my-forms">%s</a>' % _('My Forms'))
462
        if get_cfg('misc', {}).get('aq-strongbox'):
463
            profile_links.append('<a href="strongbox/">%s</a>' % _('My Strongbox'))
464
        if is_payment_supported():
465
            profile_links.append('<a href="invoices/">%s</a>' % _('My Invoices'))
466

    
467
        root_url = get_publisher().get_root_url()
468
        if user.can_go_in_backoffice():
469
            profile_links.append('<a href="%sbackoffice/">%s</a>' % (root_url, _('Back office')))
470
        if user.is_admin:
471
            profile_links.append('<a href="%sadmin/">%s</a>' % (root_url, _('Admin')))
472

    
473
        if profile_links:
474
            r += htmltext('<p id="profile-links">')
475
            r += htmltext(' - '.join(profile_links))
476
            r += htmltext('</p>')
477

    
478
        if not get_cfg('sp', {}).get('idp-manage-user-attributes', False):
479
            if user_formdef:
480
                r += self._my_profile(user_formdef, user)
481

    
482
            r += self._index_buttons(user_formdef)
483

    
484
            try:
485
                x = PasswordAccount.get_on_index(get_request().user.id, str('user_id'))
486
            except KeyError:
487
                pass
488
            else:
489
                r += htmltext('<p>')
490
                r += _('You can delete your account freely from the services portal. '
491
                       'This action is irreversible; it will destruct your personal '
492
                       'datas and destruct the access to your request history.')
493
                r += htmltext(' <strong><a href="remove" rel="popup">%s</a></strong>.') % _('Delete My Account')
494
                r += htmltext('</p>')
495

    
496
        options = get_cfg('misc', {}).get('announce_themes')
497
        if options:
498
            try:
499
                subscription = AnnounceSubscription.get_on_index(
500
                        get_request().user.id, str('user_id'))
501
            except KeyError:
502
                pass
503
            else:
504
                r += htmltext('<p class="command"><a href="announces">%s</a></p>') % _(
505
                        'Edit my Subscription to Announces')
506

    
507
        if user_forms:
508
            r += htmltext('<h3 id="my-forms">%s</h3>') % _('My Forms')
509
            r += root.FormsRootDirectory().user_forms(user_forms)
510

    
511
        return r.getvalue()
512

    
513
    def _my_profile(self, user_formdef, user):
514
        r = TemplateIO(html=True)
515
        r += htmltext('<h3 id="my-profile">%s</h3>') % _('My Profile')
516

    
517
        r += TextsDirectory.get_html_text('top-of-profile')
518

    
519
        if user.form_data:
520
            r += htmltext('<ul>')
521
            for field in user_formdef.fields:
522
                if not hasattr(field, str('get_view_value')):
523
                    continue
524
                value = user.form_data.get(field.id)
525
                r += htmltext('<li>')
526
                r += field.label
527
                r += ' : '
528
                if value:
529
                    r += field.get_view_value(value)
530
                r += htmltext('</li>')
531
            r += htmltext('</ul>')
532
        else:
533
            r += htmltext('<p>%s</p>') % _('Empty profile')
534
        return r.getvalue()
535

    
536
    def _index_buttons(self, form_data):
537
        r = TemplateIO(html=True)
538
        passwords_cfg = get_cfg('passwords', {})
539
        ident_method = get_cfg('identification', {}).get('methods', ['idp'])[0]
540
        if get_session().lasso_session_dump:
541
            ident_method = 'idp'
542

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

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

    
549
        return r.getvalue()
550

    
551
    def profile(self):
552
        user = get_request().user
553
        if not user or user.anonymous:
554
            raise errors.AccessUnauthorizedError()
555

    
556
        form = Form(enctype = 'multipart/form-data')
557
        formdef = user.get_formdef()
558
        formdef.add_fields_to_form(form, form_data = user.form_data)
559

    
560
        form.add_submit('submit', _('Apply Changes'))
561
        form.add_submit('cancel', _('Cancel'))
562

    
563
        if form.get_submit() == 'cancel':
564
            return redirect('.')
565

    
566
        if form.is_submitted() and not form.has_errors():
567
            self.profile_submit(form, formdef)
568
            return redirect('.')
569

    
570
        template.html_top(_('Edit Profile'))
571
        return form.render()
572

    
573
    def profile_submit(self, form, formdef):
574
        user = get_request().user
575
        data = formdef.get_data(form)
576

    
577
        user.set_attributes_from_formdata(data)
578
        user.form_data = data
579

    
580
        user.store()
581

    
582
    def password(self):
583
        ident_method = get_cfg('identification', {}).get('methods', ['idp'])[0]
584
        if ident_method != 'password':
585
            raise errors.TraversalError()
586

    
587
        user = get_request().user
588
        if not user or user.anonymous:
589
            raise errors.AccessUnauthorizedError()
590

    
591
        form = Form(enctype = 'multipart/form-data')
592
        form.add(PasswordWidget, 'new_password', title = _('New Password'),
593
                required=True)
594
        form.add(PasswordWidget, 'new2_password', title = _('New Password (confirm)'),
595
                required=True) 
596

    
597
        form.add_submit('submit', _('Change Password'))
598
        form.add_submit('cancel', _('Cancel'))
599

    
600
        if form.get_submit() == 'cancel':
601
            return redirect('.')
602

    
603
        if form.is_submitted() and not form.has_errors():
604
            qommon.ident.password.check_password(form, 'new_password')
605
            new_password = form.get_widget('new_password').parse()
606
            new2_password = form.get_widget('new2_password').parse()
607
            if new_password != new2_password:
608
                form.set_error('new2_password', _('Passwords do not match'))
609

    
610
        if form.is_submitted() and not form.has_errors():
611
            self.submit_password(new_password)
612
            return redirect('.')
613

    
614
        template.html_top(_('Change Password'))
615
        return form.render()
616

    
617
    def submit_password(self, new_password):
618
        passwords_cfg = get_cfg('passwords', {})
619
        account = PasswordAccount.get(get_session().username)
620
        account.hashing_algo = passwords_cfg.get('hashing_algo')
621
        account.set_password(new_password)
622
        account.store()
623

    
624
    def new(self):
625
        if not get_request().user or not get_request().user.anonymous:
626
            raise errors.AccessUnauthorizedError()
627

    
628
        form = Form(enctype = 'multipart/form-data')
629
        formdef = get_publisher().user_class.get_formdef()
630
        if formdef:
631
            formdef.add_fields_to_form(form)
632
        else:
633
            get_logger().error('missing user formdef (in myspace/new)')
634

    
635
        form.add_submit('submit', _('Register'))
636

    
637
        if form.is_submitted() and not form.has_errors():
638
            user = get_publisher().user_class()
639
            data = formdef.get_data(form)
640
            user.set_attributes_from_formdata(data)
641
            user.name_identifiers = get_request().user.name_identifiers
642
            user.lasso_dump = get_request().user.lasso_dump
643
            user.set_attributes_from_formdata(data)
644
            user.form_data = data
645
            user.store()
646
            get_session().set_user(user.id)
647
            root_url = get_publisher().get_root_url()
648
            return redirect('%smyspace' % root_url)
649

    
650
        template.html_top(_('Welcome'))
651
        return form.render()
652

    
653

    
654
    def remove(self):
655
        user = get_request().user
656
        if not user or user.anonymous:
657
            raise errors.AccessUnauthorizedError()
658

    
659
        form = Form(enctype = 'multipart/form-data')
660
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
661
                        'Are you really sure you want to remove your account?')))
662
        form.add_submit('submit', _('Remove my account'))
663
        form.add_submit('cancel', _('Cancel'))
664

    
665
        if form.get_submit() == 'cancel':
666
            return redirect('.')
667

    
668
        if form.is_submitted() and not form.has_errors():
669
            user = get_request().user
670
            account = PasswordAccount.get_on_index(user.id, str('user_id'))
671
            get_session_manager().expire_session() 
672
            account.remove_self()
673
            return redirect(get_publisher().get_root_url())
674

    
675
        template.html_top(_('Removing Account'))
676
        return form.render()
677

    
678
    def announces(self):
679
        options = get_cfg('misc', {}).get('announce_themes')
680
        if not options:
681
            raise errors.TraversalError()
682
        user = get_request().user
683
        if not user or user.anonymous:
684
            raise errors.AccessUnauthorizedError()
685
        subscription = AnnounceSubscription.get_on_index(get_request().user.id, str('user_id'))
686
        if not subscription:
687
            raise errors.TraversalError()
688

    
689
        if subscription.enabled_themes is None:
690
            enabled_themes = options
691
        else:
692
            enabled_themes = subscription.enabled_themes
693

    
694
        form = Form(enctype = 'multipart/form-data')
695
        form.add(CheckboxesWidget, 'themes', title=_('Announce Themes'),
696
                value=enabled_themes, options=[(x, x, x) for x in options],
697
                inline=False, required=False)
698

    
699
        form.add_submit('submit', _('Apply Changes'))
700
        form.add_submit('cancel', _('Cancel'))
701

    
702
        if form.get_submit() == 'cancel':
703
            return redirect('.')
704

    
705
        if form.is_submitted() and not form.has_errors():
706
            chosen_themes = form.get_widget('themes').parse()
707
            if chosen_themes == options:
708
                chosen_themes = None
709
            subscription.enabled_themes = chosen_themes
710
            subscription.store()
711
            return redirect('.')
712

    
713
        template.html_top()
714
        get_response().breadcrumb.append(('announces', _('Announce Subscription')))
715
        return form.render()
716

    
717

    
718
TextsDirectory.register('aq-myspace-invoice',
719
        N_('Message on top of invoices page'),
720
        category = N_('Invoices'))
721

    
(20-20/27)