Statistics
| Branch: | Tag: | Revision:

root / astakos / im / views.py @ 64cd4730

History | View | Annotate | Download (26.1 kB)

1
# Copyright 2011 GRNET S.A. All rights reserved.
2
# 
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
# 
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
# 
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
# 
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
# 
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
import json
35
import logging
36
import socket
37
import csv
38
import sys
39

    
40
from datetime import datetime
41
from functools import wraps
42
from math import ceil
43
from random import randint
44
from smtplib import SMTPException
45

    
46
from django.conf import settings
47
from django.core.mail import send_mail
48
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest
49
from django.shortcuts import redirect
50
from django.template.loader import render_to_string
51
from django.shortcuts import render_to_response
52
from django.utils.http import urlencode
53
from django.utils.translation import ugettext as _
54
from django.core.urlresolvers import reverse
55
from django.forms import Form
56
from django.forms.formsets import formset_factory
57
#from openid.consumer.consumer import Consumer, \
58
#    SUCCESS, CANCEL, FAILURE, SETUP_NEEDED
59

    
60
from hashlib import new as newhasher
61

    
62
from urllib import quote
63

    
64
#from astakos.im.openid_store import PithosOpenIDStore
65
from astakos.im.models import User, Invitation
66
from astakos.im.util import isoformat
67
from astakos.im.forms import *
68

    
69
def render_response(template, tab=None, status=200, **kwargs):
70
    if tab is None:
71
        tab = template.partition('_')[0]
72
    kwargs.setdefault('tab', tab)
73
    html = render_to_string(template, kwargs)
74
    return HttpResponse(html, status=status)
75

    
76

    
77
def requires_login(func):
78
    @wraps(func)
79
    def wrapper(request, *args):
80
        if not settings.BYPASS_ADMIN_AUTH:
81
            if not request.user:
82
                next = urlencode({'next': request.build_absolute_uri()})
83
                login_uri = reverse(index) + '?' + next
84
                return HttpResponseRedirect(login_uri)
85
        return func(request, *args)
86
    return wrapper
87

    
88
def requires_admin(func):
89
    @wraps(func)
90
    def wrapper(request, *args):
91
        if not settings.BYPASS_ADMIN_AUTH:
92
            if not request.user:
93
                next = urlencode({'next': request.build_absolute_uri()})
94
                login_uri = reverse(index) + '?' + next
95
                return HttpResponseRedirect(login_uri)
96
            if not request.user.is_admin:
97
                return HttpResponse('Forbidden', status=403)
98
        return func(request, *args)
99
    return wrapper
100

    
101

    
102
def index(request):
103
    kwargs = {'im_modules':settings.IM_MODULES,
104
              'other_modules':settings.IM_MODULES[1:]}
105
    return render_response('index.html',
106
                           next=request.GET.get('next', ''),
107
                           **kwargs)
108

    
109

    
110
@requires_admin
111
def admin(request):
112
    stats = {}
113
    stats['users'] = User.objects.count()
114
    stats['pending'] = User.objects.filter(state = 'PENDING').count()
115
    
116
    invitations = Invitation.objects.all()
117
    stats['invitations'] = invitations.count()
118
    stats['invitations_consumed'] = invitations.filter(is_consumed=True).count()
119
    
120
    return render_response('admin.html', tab='home', stats=stats)
121

    
122

    
123
@requires_admin
124
def users_list(request):
125
    users = User.objects.order_by('id')
126
    
127
    filter = request.GET.get('filter', '')
128
    if filter:
129
        if filter.startswith('-'):
130
            users = users.exclude(uniq__icontains=filter[1:])
131
        else:
132
            users = users.filter(uniq__icontains=filter)
133
    
134
    try:
135
        page = int(request.GET.get('page', 1))
136
    except ValueError:
137
        page = 1
138
    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
139
    limit = offset + settings.ADMIN_PAGE_LIMIT
140
    
141
    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
142
    prev = page - 1 if page > 1 else None
143
    next = page + 1 if page < npages else None
144
    return render_response('users_list.html',
145
                            users=users[offset:limit],
146
                            filter=filter,
147
                            pages=range(1, npages + 1),
148
                            page=page,
149
                            prev=prev,
150
                            next=next)
151

    
152
@requires_admin
153
def users_info(request, user_id):
154
    user = User.objects.get(id=user_id)
155
    states = [x[0] for x in User.ACCOUNT_STATE]
156
    return render_response('users_info.html',
157
                            user=user,
158
                            states=states)
159

    
160

    
161
@requires_admin
162
def users_modify(request, user_id):
163
    user = User.objects.get(id=user_id)
164
    user.uniq = request.POST.get('uniq')
165
    user.realname = request.POST.get('realname')
166
    user.is_admin = True if request.POST.get('admin') else False
167
    user.affiliation = request.POST.get('affiliation')
168
    user.state = request.POST.get('state')
169
    user.invitations = int(request.POST.get('invitations') or 0)
170
    user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
171
    user.auth_token = request.POST.get('auth_token')
172
    try:
173
        auth_token_expires = request.POST.get('auth_token_expires')
174
        d = datetime.strptime(auth_token_expires, '%Y-%m-%dT%H:%MZ')
175
        user.auth_token_expires = d
176
    except ValueError:
177
        pass
178
    user.save()
179
    return redirect(users_info, user.id)
180

    
181
@requires_admin
182
def users_delete(request, user_id):
183
    user = User.objects.get(id=user_id)
184
    user.delete()
185
    return redirect(users_list)
186

    
187
@requires_admin
188
def pending_users(request):
189
    users = User.objects.order_by('id')
190
    
191
    users = users.filter(state = 'PENDING')
192
    
193
    try:
194
        page = int(request.GET.get('page', 1))
195
    except ValueError:
196
        page = 1
197
    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
198
    limit = offset + settings.ADMIN_PAGE_LIMIT
199
    
200
    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
201
    prev = page - 1 if page > 1 else None
202
    next = page + 1 if page < npages else None
203
    return render_response('pending_users.html',
204
                            users=users[offset:limit],
205
                            filter=filter,
206
                            pages=range(1, npages + 1),
207
                            page=page,
208
                            prev=prev,
209
                            next=next)
210

    
211
def send_greeting(baseurl, user):
212
    url = baseurl
213
    subject = _('Welcome to Pithos')
214
    message = render_to_string('welcome.txt', {
215
                'user': user,
216
                'url': url,
217
                'baseurl': baseurl,
218
                'service': settings.SERVICE_NAME,
219
                'support': settings.DEFAULT_CONTACT_EMAIL})
220
    sender = settings.DEFAULT_FROM_EMAIL
221
    send_mail(subject, message, sender, [user.email])
222
    logging.info('Sent greeting %s', user)
223

    
224
@requires_admin
225
def users_activate(request, user_id):
226
    user = User.objects.get(id=user_id)
227
    user.state = 'ACTIVE'
228
    status = 'success'
229
    try:
230
        send_greeting(request.build_absolute_uri('/').rstrip('/'), user)
231
        message = _('Greeting sent to %s' % user.email)
232
        user.save()
233
    except (SMTPException, socket.error) as e:
234
        status = 'error'
235
        name = 'strerror'
236
        message = getattr(e, name) if hasattr(e, name) else e
237
    
238
    users = User.objects.order_by('id')
239
    users = users.filter(state = 'PENDING')
240
    
241
    try:
242
        page = int(request.POST.get('page', 1))
243
    except ValueError:
244
        page = 1
245
    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
246
    limit = offset + settings.ADMIN_PAGE_LIMIT
247
    
248
    npages = int(ceil(1.0 * users.count() / settings.ADMIN_PAGE_LIMIT))
249
    prev = page - 1 if page > 1 else None
250
    next = page + 1 if page < npages else None
251
    return render_response('pending_users.html',
252
                            users=users[offset:limit],
253
                            filter=filter,
254
                            pages=range(1, npages + 1),
255
                            page=page,
256
                            prev=prev,
257
                            next=next,
258
                            message=message)
259

    
260
def generate_invitation_code():
261
    while True:
262
        code = randint(1, 2L**63 - 1)
263
        try:
264
            Invitation.objects.get(code=code)
265
            # An invitation with this code already exists, try again
266
        except Invitation.DoesNotExist:
267
            return code
268

    
269

    
270
def send_invitation(baseurl, inv):
271
    url = settings.SIGNUP_TARGET % (baseurl, inv.code, quote(baseurl))
272
    subject = _('Invitation to Pithos')
273
    message = render_to_string('invitation.txt', {
274
                'invitation': inv,
275
                'url': url,
276
                'baseurl': baseurl,
277
                'service': settings.SERVICE_NAME,
278
                'support': settings.DEFAULT_CONTACT_EMAIL})
279
    sender = settings.DEFAULT_FROM_EMAIL
280
    send_mail(subject, message, sender, [inv.uniq])
281
    logging.info('Sent invitation %s', inv)
282

    
283

    
284
@requires_login
285
def invite(request):
286
    status = None
287
    message = None
288
    inviter = request.user
289

    
290
    if request.method == 'POST':
291
        uniq = request.POST.get('uniq')
292
        realname = request.POST.get('realname')
293
        
294
        if inviter.invitations > 0:
295
            code = generate_invitation_code()
296
            invitation, created = Invitation.objects.get_or_create(
297
                inviter=inviter,
298
                uniq=uniq,
299
                defaults={'code': code, 'realname': realname})
300
            
301
            try:
302
                send_invitation(request.build_absolute_uri('/').rstrip('/'), invitation)
303
                if created:
304
                    inviter.invitations = max(0, inviter.invitations - 1)
305
                    inviter.save()
306
                status = 'success'
307
                message = _('Invitation sent to %s' % uniq)
308
            except (SMTPException, socket.error) as e:
309
                status = 'error'
310
                message = getattr(e, 'strerror', '')
311
        else:
312
            status = 'error'
313
            message = _('No invitations left')
314

    
315
    if request.GET.get('format') == 'json':
316
        sent = [{'email': inv.uniq,
317
                 'realname': inv.realname,
318
                 'is_accepted': inv.is_accepted}
319
                    for inv in inviter.invitations_sent.all()]
320
        rep = {'invitations': inviter.invitations, 'sent': sent}
321
        return HttpResponse(json.dumps(rep))
322
    
323
    html = render_to_string('invitations.html', {
324
            'user': inviter,
325
            'status': status,
326
            'message': message})
327
    return HttpResponse(html)
328

    
329
def send_verification(baseurl, user):
330
    url = settings.ACTIVATION_LOGIN_TARGET % (baseurl,
331
                                              quote(user.auth_token),
332
                                              quote(baseurl))
333
    message = render_to_string('activation.txt', {
334
            'user': user,
335
            'url': url,
336
            'baseurl': baseurl,
337
            'service': settings.SERVICE_NAME,
338
            'support': settings.DEFAULT_CONTACT_EMAIL})
339
    sender = settings.DEFAULT_FROM_EMAIL
340
    send_mail('Pithos account activation', message, sender, [user.email])
341
    logging.info('Sent activation %s', user)
342

    
343
def send_password(baseurl, user):
344
    url = settings.PASSWORD_RESET_TARGET % (baseurl,
345
                                            quote(user.uniq),
346
                                            quote(baseurl))
347
    message = render_to_string('password.txt', {
348
            'user': user,
349
            'url': url,
350
            'baseurl': baseurl,
351
            'service': settings.SERVICE_NAME,
352
            'support': settings.DEFAULT_CONTACT_EMAIL})
353
    sender = settings.DEFAULT_FROM_EMAIL
354
    send_mail('Pithos password recovering', message, sender, [user.email])
355
    logging.info('Sent password %s', user)
356

    
357
def reclaim_password(request):
358
    if request.method == 'GET':
359
        return render_response('reclaim.html')
360
    elif request.method == 'POST':
361
        username = request.POST.get('uniq')
362
        try:
363
            user = User.objects.get(uniq=username)
364
            try:
365
                send_password(request.build_absolute_uri('/').rstrip('/'), user)
366
                status = 'success'
367
                message = _('Password reset sent to %s' % user.email)
368
                user.status = 'UNVERIFIED'
369
                user.save()
370
            except (SMTPException, socket.error) as e:
371
                status = 'error'
372
                name = 'strerror'
373
                message = getattr(e, name) if hasattr(e, name) else e
374
        except User.DoesNotExist:
375
            status = 'error'
376
            message = 'Username does not exist'
377
        
378
        html = render_to_string('reclaim.html', {
379
                'status': status,
380
                'message': message})
381
        return HttpResponse(html)
382

    
383
@requires_admin
384
def invitations_list(request):
385
    invitations = Invitation.objects.order_by('id')
386
    
387
    filter = request.GET.get('filter', '')
388
    if filter:
389
        if filter.startswith('-'):
390
            invitations = invitations.exclude(uniq__icontains=filter[1:])
391
        else:
392
            invitations = invitations.filter(uniq__icontains=filter)
393
    
394
    try:
395
        page = int(request.GET.get('page', 1))
396
    except ValueError:
397
        page = 1
398
    offset = max(0, page - 1) * settings.ADMIN_PAGE_LIMIT
399
    limit = offset + settings.ADMIN_PAGE_LIMIT
400
    
401
    npages = int(ceil(1.0 * invitations.count() / settings.ADMIN_PAGE_LIMIT))
402
    prev = page - 1 if page > 1 else None
403
    next = page + 1 if page < npages else None
404
    return render_response('invitations_list.html',
405
                            invitations=invitations[offset:limit],
406
                            filter=filter,
407
                            pages=range(1, npages + 1),
408
                            page=page,
409
                            prev=prev,
410
                            next=next)
411

    
412
@requires_admin
413
def invitations_export(request):
414
    # Create the HttpResponse object with the appropriate CSV header.
415
    response = HttpResponse(mimetype='text/csv')
416
    response['Content-Disposition'] = 'attachment; filename=invitations.csv'
417

    
418
    writer = csv.writer(response)
419
    writer.writerow(['ID',
420
                     'Uniq',
421
                     'Real Name',
422
                     'Code',
423
                     'Inviter Uniq',
424
                     'Inviter Real Name',
425
                     'Is_accepted',
426
                     'Created',
427
                     'Accepted',])
428
    invitations = Invitation.objects.order_by('id')
429
    for inv in invitations:
430
        writer.writerow([inv.id,
431
                         inv.uniq.encode("utf-8"),
432
                         inv.realname.encode("utf-8"),
433
                         inv.code,
434
                         inv.inviter.uniq.encode("utf-8"),
435
                         inv.inviter.realname.encode("utf-8"),
436
                         inv.is_accepted,
437
                         inv.created,
438
                         inv.accepted])
439

    
440
    return response
441

    
442

    
443
@requires_admin
444
def users_export(request):
445
    # Create the HttpResponse object with the appropriate CSV header.
446
    response = HttpResponse(mimetype='text/csv')
447
    response['Content-Disposition'] = 'attachment; filename=users.csv'
448

    
449
    writer = csv.writer(response)
450
    writer.writerow(['ID',
451
                     'Uniq',
452
                     'Real Name',
453
                     'Admin',
454
                     'Affiliation',
455
                     'State',
456
                     'Quota (GiB)',
457
                     'Updated',])
458
    users = User.objects.order_by('id')
459
    for u in users:
460
        writer.writerow([u.id,
461
                         u.uniq.encode("utf-8"),
462
                         u.realname.encode("utf-8"),
463
                         u.is_admin,
464
                         u.affiliation.encode("utf-8"),
465
                         u.state.encode("utf-8"),
466
                         u.quota,
467
                         u.updated])
468

    
469
    return response
470

    
471
@requires_admin
472
def users_create(request):
473
    if request.method == 'GET':
474
        return render_response('users_local_create.html')
475
    if request.method == 'POST':
476
        user = User()
477
        user.uniq = request.POST.get('uniq')
478
        user.realname = request.POST.get('realname')
479
        user.is_admin = True if request.POST.get('admin') else False
480
        user.affiliation = request.POST.get('affiliation')
481
        user.quota = int(request.POST.get('quota') or 0) * (1024 ** 3)  # In GiB
482
        user.renew_token()
483
        user.provider = 'local'
484
        user.save()
485
        return redirect(users_info, user.id)
486

    
487
@requires_login
488
def users_profile(request):
489
    next = request.GET.get('next')
490
    try:
491
        user = User.objects.get(uniq=request.user)
492
    except User.DoesNotExist:
493
        user = User.objects.get(auth_token=request.GET.get('auth', None))
494
    states = [x[0] for x in User.ACCOUNT_STATE]
495
    return render_response('users_profile.html',
496
                            user=user,
497
                            states=states,
498
                            next=next)
499

    
500
@requires_login
501
def users_edit(request):
502
    try:
503
        user = User.objects.get(uniq=request.user)
504
    except User.DoesNotExist:
505
        token = request.POST.get('auth', None)
506
        users = User.objects.all()
507
        user = User.objects.get(auth_token=token)
508
    user.realname = request.POST.get('realname')
509
    user.affiliation = request.POST.get('affiliation')
510
    user.is_verified = True
511
    user.save()
512
    next = request.POST.get('next')
513
    if next:
514
        return redirect(next)
515
    
516
    status = 'success'
517
    message = _('Profile has been updated')
518
    html = render_to_string('users_profile.html', {
519
            'user': user,
520
            'status': status,
521
            'message': message})
522
    return HttpResponse(html)
523
    
524
def signup(request):
525
    if request.method == 'GET':
526
        kwargs = {'im_modules':settings.IM_MODULES,
527
                  'next':request.GET.get('next', ''),
528
                  'code':request.GET.get('code', '')}
529
        return render_response('signup.html', **kwargs)
530
    elif request.method == 'POST':
531
        provider = request.POST.get('choice')
532
        if not provider:
533
            return on_failure(_('No provider selected'), template='signup.html')
534
        
535
        kwargs = {'code':request.POST.get('code', ''),
536
                  'next':request.POST.get('next', '')}
537
        url = '%s%s?' %(reverse('astakos.im.views.register'), provider)
538
        for k,v in kwargs.items():
539
            if v:
540
                url = '%s%s=%s&' %(url, k, v)
541
        return redirect(url)
542

    
543
def render_registration(provider, code='', next=''):
544
    initial_data = {'provider':provider}
545
    if settings.INVITATIONS_ENABLED and code:
546
        try:
547
            print '#', type(code), code
548
            invitation = Invitation.objects.get(code=code)
549
            if invitation.is_consumed:
550
                return HttpResponseBadRequest('Invitation has beeen used')
551
            initial_data.update({'uniq':invitation.uniq,
552
                                 'email':invitation.uniq,
553
                                 'realname':invitation.realname})
554
            try:
555
                inviter = User.objects.get(uniq=invitation.inviter)
556
                initial_data['inviter'] = inviter.realname
557
            except User.DoesNotExist:
558
                pass
559
        except Invitation.DoesNotExist:
560
            return on_failure(_('Wrong invitation code'), template='register.html')
561
    
562
    prefix = 'Invited' if code else ''
563
    formclassname = '%s%sRegisterForm' %(prefix, provider.capitalize())
564
    formclass_ = getattr(sys.modules['astakos.im.forms'], formclassname)
565
    RegisterFormSet = formset_factory(formclass_, extra=0)
566
    formset = RegisterFormSet(initial=[initial_data])
567
    return render_response('register.html',
568
                           formset=formset,
569
                           next=next,
570
                           filter=filter,
571
                           code=code)
572

    
573
def is_preaccepted(user):
574
    if user.invitation and not user.invitation.is_consumed:
575
        return True
576
    
577
    return False
578

    
579
def should_send_verification():
580
    if not settings.INVITATIONS_ENABLED:
581
        return True    
582
    return False
583

    
584
def register(request, provider):
585
    print '---', request
586
    code = request.GET.get('code')
587
    next = request.GET.get('next')
588
    if request.method == 'GET':
589
        code = request.GET.get('code', '')
590
        next = request.GET.get('next', '')
591
        if provider not in settings.IM_MODULES:
592
            return on_failure(_('Invalid provider'))
593
        return render_registration(provider, code, next)
594
    elif request.method == 'POST':
595
        provider = request.POST.get('form-0-provider')
596
        inviter = request.POST.get('form-0-inviter')
597
        
598
        #instantiate the form
599
        prefix = 'Invited' if inviter else ''
600
        formclassname = '%sRegisterForm' %(provider.capitalize())
601
        formclass_ = getattr(sys.modules['astakos.im.forms'], formclassname)
602
        RegisterFormSet = formset_factory(formclass_, extra=0)
603
        formset = RegisterFormSet(request.POST)
604
        if not formset.is_valid():
605
            return render_to_response('register.html',
606
                                      {'formset':formset,
607
                                       'code':code,
608
                                       'next':next}) 
609
        
610
        user = User()
611
        for form in formset.forms:
612
            for field in form.fields:
613
                if hasattr(user, field):
614
                    setattr(user, field, form.cleaned_data[field])
615
            break
616
        
617
        if user.openidurl:
618
            redirect_url = reverse('astakos.im.views.create')
619
            return ask_openid(request, 
620
                        user.openidurl,
621
                        redirect_url,
622
                        'signup')
623
        
624
        #save hashed password
625
        if user.password:
626
            hasher = newhasher('sha256')
627
            hasher.update(user.password)
628
            user.password = hasher.hexdigest() 
629
            
630
        user.renew_token()
631
        
632
        if is_preaccepted(user):
633
            user.state = 'ACTIVE'
634
            user.save()
635
            url = reverse('astakos.im.views.index')
636
            return redirect(url)
637
        
638
        status = 'success'
639
        if should_send_verification():
640
            try:
641
                send_verification(request.build_absolute_uri('/').rstrip('/'), user)
642
                message = _('Verification sent to %s' % user.email)
643
                user.save()
644
            except (SMTPException, socket.error) as e:
645
                status = 'error'
646
                name = 'strerror'
647
                message = getattr(e, name) if hasattr(e, name) else e
648
        else:
649
            user.save()
650
            message = _('Registration completed. You will receive an email upon your account\'s activation')
651
        
652
        return info(status, message)
653

    
654
#def discover_extensions(openid_url):
655
#    service = discover(openid_url)
656
#    use_ax = False
657
#    use_sreg = False
658
#    for endpoint in service[1]:
659
#        if not use_sreg:
660
#            use_sreg = sreg.supportsSReg(endpoint)
661
#        if not use_ax:
662
#            use_ax = endpoint.usesExtension("http://openid.net/srv/ax/1.0")
663
#        if use_ax and use_sreg: break
664
#    return use_ax, use_sreg
665
#
666
#def ask_openid(request, openid_url, redirect_to, on_failure=None):
667
#    """ basic function to ask openid and return response """
668
#    on_failure = on_failure or signin_failure
669
#    sreg_req = None
670
#    ax_req = None
671
#    
672
#    trust_root = getattr(
673
#        settings, 'OPENID_TRUST_ROOT', request.build_absolute_uri() + '/'
674
#    )
675
#    request.session = {}
676
#    consumer = Consumer(request.session, PithosOpenIDStore())
677
#    try:
678
#        auth_request = consumer.begin(openid_url)
679
#    except DiscoveryFailure:
680
#        msg = _("The OpenID %s was invalid") % openid_url
681
#        return on_failure(request, msg)
682
#    
683
#     get capabilities
684
#    use_ax, use_sreg = discover_extensions(openid_url)
685
#    if use_sreg:
686
#         set sreg extension
687
#         we always ask for nickname and email
688
#        sreg_attrs = getattr(settings, 'OPENID_SREG', {})
689
#        sreg_attrs.update({ "optional": ['nickname', 'email'] })
690
#        sreg_req = sreg.SRegRequest(**sreg_attrs)
691
#    if use_ax:
692
#         set ax extension
693
#         we always ask for nickname and email
694
#        ax_req = ax.FetchRequest()
695
#        ax_req.add(ax.AttrInfo('http://schema.openid.net/contact/email', 
696
#                                alias='email', required=True))
697
#        ax_req.add(ax.AttrInfo('http://schema.openid.net/namePerson/friendly', 
698
#                                alias='nickname', required=True))
699
#                      
700
#         add custom ax attrs          
701
#        ax_attrs = getattr(settings, 'OPENID_AX', [])
702
#        for attr in ax_attrs:
703
#            if len(attr) == 2:
704
#                ax_req.add(ax.AttrInfo(attr[0], required=alias[1]))
705
#            else:
706
#                ax_req.add(ax.AttrInfo(attr[0]))
707
#       
708
#    if sreg_req is not None:
709
#        auth_request.addExtension(sreg_req)
710
#    if ax_req is not None:
711
#        auth_request.addExtension(ax_req)
712
#    
713
#    redirect_url = auth_request.redirectURL(trust_root, redirect_to)
714
#    return HttpResponseRedirect(redirect_url)
715

    
716
def info(status, message, template='base.html'):
717
    html = render_to_string(template, {
718
            'status': status,
719
            'message': message})
720
    response = HttpResponse(html)
721
    return response
722

    
723
def on_success(message, template='base.html'):
724
    return info('success', message)
725
    
726
def on_failure(message, template='base.html'):
727
    return info('error', message)