Using Piston auth in DRF views. Replacing API views.
[wolnelektury.git] / src / api / piston_patch.py
1 # -*- coding: utf-8 -*-
2
3 # modified from django-piston
4 import base64
5 import hmac
6
7 from django import forms
8 from django.conf import settings
9 from django.contrib.auth.decorators import login_required
10 from django.core.urlresolvers import get_callable
11 from django.http import HttpResponseRedirect, HttpResponse
12 from django.shortcuts import render_to_response
13 from django.template.context import RequestContext
14 from piston import oauth
15 from piston.authentication import initialize_server_request, INVALID_PARAMS_RESPONSE, send_oauth_error
16
17
18 class HttpResponseAppRedirect(HttpResponseRedirect):
19     allowed_schemes = HttpResponseRedirect.allowed_schemes + ['wolnelekturyapp']
20
21
22 class OAuthAuthenticationForm(forms.Form):
23     oauth_token = forms.CharField(widget=forms.HiddenInput)
24     oauth_callback = forms.CharField(widget=forms.HiddenInput)  # changed from URLField - too strict
25     # removed authorize_access - redundant
26     csrf_signature = forms.CharField(widget=forms.HiddenInput)
27
28     def __init__(self, *args, **kwargs):
29         forms.Form.__init__(self, *args, **kwargs)
30
31         self.fields['csrf_signature'].initial = self.initial_csrf_signature
32
33     def clean_csrf_signature(self):
34         sig = self.cleaned_data['csrf_signature']
35         token = self.cleaned_data['oauth_token']
36
37         sig1 = OAuthAuthenticationForm.get_csrf_signature(settings.SECRET_KEY, token)
38
39         if sig != sig1:
40             raise forms.ValidationError("CSRF signature is not valid")
41
42         return sig
43
44     def initial_csrf_signature(self):
45         token = self.initial['oauth_token']
46         return OAuthAuthenticationForm.get_csrf_signature(settings.SECRET_KEY, token)
47
48     @staticmethod
49     def get_csrf_signature(key, token):
50         # Check signature...
51         import hashlib  # 2.5
52         hashed = hmac.new(key, token, hashlib.sha1)
53
54         # calculate the digest base 64
55         return base64.b64encode(hashed.digest())
56
57
58 # The only thing changed in the views below is the form used
59 # and also the Http Redirect class
60
61
62 def oauth_auth_view(request, token, callback, params):
63     form = OAuthAuthenticationForm(initial={
64         'oauth_token': token.key,
65         'oauth_callback': callback,
66     })
67
68     return render_to_response('piston/authorize_token.html',
69                               {'form': form}, RequestContext(request))
70
71
72 @login_required
73 def oauth_user_auth(request):
74     oauth_server, oauth_request = initialize_server_request(request)
75
76     if oauth_request is None:
77         return INVALID_PARAMS_RESPONSE
78
79     try:
80         token = oauth_server.fetch_request_token(oauth_request)
81     except oauth.OAuthError, err:
82         return send_oauth_error(err)
83
84     try:
85         callback = oauth_server.get_callback(oauth_request)
86     except:
87         callback = None
88
89     if request.method == "GET":
90         params = oauth_request.get_normalized_parameters()
91
92         oauth_view = getattr(settings, 'OAUTH_AUTH_VIEW', None)
93         if oauth_view is None:
94             return oauth_auth_view(request, token, callback, params)
95         else:
96             return get_callable(oauth_view)(request, token, callback, params)
97     elif request.method == "POST":
98         try:
99             form = OAuthAuthenticationForm(request.POST)
100             if form.is_valid():
101                 token = oauth_server.authorize_token(token, request.user)
102                 args = '?' + token.to_string(only_key=True)
103             else:
104                 args = '?error=%s' % 'Access not granted by user.'
105
106             if not callback:
107                 callback = getattr(settings, 'OAUTH_CALLBACK_VIEW')
108                 return get_callable(callback)(request, token)
109
110             response = HttpResponseAppRedirect(callback + args)
111
112         except oauth.OAuthError, err:
113             response = send_oauth_error(err)
114     else:
115         response = HttpResponse('Action not allowed.')
116
117     return response