~isagalaev/scipio/trunk

1 by Ivan Sagalaev
Scipio. Initial commit.
1
# -*- coding:utf-8 -*-
2
from django.views.decorators.http import require_POST
3
from django import http
4
from django.utils.translation import ugettext as _
5
from django.utils import simplejson
9 by Ivan Sagalaev
Починка вывода login-страницы при ошибках валидации OpenID URL
6
from django.shortcuts import redirect, render_to_response
7
from django.template import RequestContext
1 by Ivan Sagalaev
Scipio. Initial commit.
8
from django.contrib import auth
9
16 by Ivan Sagalaev
Реорганизация utils в пакет.
10
from scipio import models, forms, signals
11
from scipio.utils import mimeparse
1 by Ivan Sagalaev
Scipio. Initial commit.
12
13
def _post_redirect(request):
14
    return request.POST.get('redirect', request.META.get('HTTP_REFERER', '/'))
15
16
def login(request):
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
17
    """
18
    Shows and processes an OpenID login form. The successful response from the
19
    view is a redirect to user's OpenID server. The server will then return the
20
    user back to `complete` view.
21
22
    Requires a template "scipio/login.html".
23
    """
1 by Ivan Sagalaev
Scipio. Initial commit.
24
    if request.method == 'POST':
25
        form = forms.AuthForm(request.session, request.POST)
26
        if form.is_valid():
3 by Ivan Sagalaev
Авторизация не должна автоматически логинить юзера.
27
            after_auth_redirect = form.auth_redirect(_post_redirect(request), {'op': 'login'})
1 by Ivan Sagalaev
Scipio. Initial commit.
28
            return redirect(after_auth_redirect)
29
        return_url = _post_redirect(request)
30
    else:
31
        form = forms.AuthForm(request.session)
32
        return_url = request.GET.get('redirect', '/')
9 by Ivan Sagalaev
Починка вывода login-страницы при ошибках валидации OpenID URL
33
    return render_to_response('scipio/login.html',
34
        {'form': form, 'redirect': return_url},
35
        context_instance = RequestContext(request),
36
    )
1 by Ivan Sagalaev
Scipio. Initial commit.
37
38
def complete(request, message=_('Authentication failed')):
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
39
    """
40
    Completes authentication process after user returns from the OpenID server.
41
42
    If authentication is successful sends a signal about it which an
43
    application can catch and return some HttpResponse. If no HttpResponse
44
    returned from signal handlers the view just redirect a user to the original
45
    page from which authentication had started.
46
    """
1 by Ivan Sagalaev
Scipio. Initial commit.
47
    user = auth.authenticate(session=request.session, query=request.GET, return_path=request.path)
48
    if not user:
49
        return http.HttpResponseForbidden(message)
2 by Ivan Sagalaev
str для ключей data при передаче в сигнал
50
    data = dict((str(k[7:]), v) for k, v in request.GET.items() if k.startswith('scipio.'))
3 by Ivan Sagalaev
Авторизация не должна автоматически логинить юзера.
51
    results = signals.authenticated.send(request, user=user, **data)
39 by Ivan Sagalaev
Treat results from a signal call as a list of tuple of (callback, result)
52
    for callback, result in results:
53
        if isinstance(result, http.HttpResponse):
54
            response = result
1 by Ivan Sagalaev
Scipio. Initial commit.
55
            break
56
    else:
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
57
        response = redirect(request.GET.get('redirect', '/'))
58
    return response
1 by Ivan Sagalaev
Scipio. Initial commit.
59
3 by Ivan Sagalaev
Авторизация не должна автоматически логинить юзера.
60
def complete_login(sender, user, op=None, **kwargs):
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
61
    """
62
    A default handler for login completion that actually athenticates a Django
63
    user and persists it in a session.
64
    """
3 by Ivan Sagalaev
Авторизация не должна автоматически логинить юзера.
65
    if op == 'login':
66
        auth.login(sender, user)
67
signals.authenticated.connect(complete_login)
68
1 by Ivan Sagalaev
Scipio. Initial commit.
69
@require_POST
70
def logout(request):
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
71
    """
72
    Processes logout form by logging out Django user.
73
    """
1 by Ivan Sagalaev
Scipio. Initial commit.
74
    auth.logout(request)
75
    return redirect(_post_redirect(request))
76
77
def openid_whitelist(request):
34 by Ivan Sagalaev
Stylistic fixes in comments for settings.
78
    """
79
    Shows current list of white-listed users to share it with whoever wants to
80
    know users trusted by this site.
81
82
    The list is available in three formats (text, xml, json). The format is
83
    negotiated by HTTP spec using Accept header.
84
    """
1 by Ivan Sagalaev
Scipio. Initial commit.
85
    if request.method == 'POST':
86
        try:
87
            profile = models.Profile.objects.get(pk=int(request.POST['id']))
88
            profile.spamer = False
89
            profile.save()
11 by Ivan Sagalaev
Сигнал whitelist
90
            signals.whitelist.send(sender=profile)
1 by Ivan Sagalaev
Scipio. Initial commit.
91
            return redirect(_post_redirect(request))
14 by maniac
Ссылка на Profile через models.Profile в openid_whitelist
92
        except (models.Profile.DoesNotExist, ValueError, KeyError):
1 by Ivan Sagalaev
Scipio. Initial commit.
93
            return http.HttpResponseBadRequest()
94
    else:
14 by maniac
Ссылка на Profile через models.Profile в openid_whitelist
95
        openids = (p.openid for p in models.Profile.objects.filter(spamer=False) if p.openid)
1 by Ivan Sagalaev
Scipio. Initial commit.
96
        MIMETYPES = ['application/xml', 'text/xml', 'application/json', 'text/plain']
97
        accept = request.META.get('HTTP_ACCEPT', '')
98
        try:
99
            mimetype = mimeparse.best_match(MIMETYPES, accept)
100
        except ValueError:
101
            mimetype = 'text/plain'
102
        if mimetype.endswith('/xml'):
103
            try:
104
                import xml.etree.ElementTree as ET
105
            except ImportError:
106
                import elementtree.ElementTree as ET
107
            root = ET.Element('whitelist')
108
            for openid in openids:
109
                ET.SubElement(root, 'openid').text = openid
110
            xml = ET.ElementTree(root)
111
            response = http.HttpResponse(mimetype=mimetype)
112
            xml.write(response, encoding='utf-8')
113
            return response
114
        if mimetype == 'application/json':
115
            response = http.HttpResponse(mimetype=mimetype)
116
            simplejson.dump(list(openids), response)
117
            return response
118
        if mimetype == 'text/plain':
119
            return http.HttpResponse((o + '\n' for o in openids), mimetype=mimetype)
120
        return http.HttpResponse('Can accept only: %s' % ', '.join(MIMETYPES), status=406)