Last Piston view replaced using OAuthlib.
authorRadek Czajka <rczajka@rczajka.pl>
Fri, 8 Feb 2019 10:18:58 +0000 (11:18 +0100)
committerRadek Czajka <rczajka@rczajka.pl>
Fri, 8 Feb 2019 10:18:58 +0000 (11:18 +0100)
src/api/request_validator.py
src/api/tests/tests.py
src/api/urls.py
src/api/views.py

index 6e3c0c2..916636b 100644 (file)
@@ -21,18 +21,37 @@ class PistonRequestValidator(RequestValidator):
     nonce_length = 8, 250
 
     # Because piston.models.Token.key is char(18).
+    request_token_length = 18, 32
     access_token_length = 18, 32
+    # TODO: oauthlib request-access switch.
 
     def check_client_key(self, client_key):
         """We control the keys anyway."""
         return True
 
+    def get_request_token_secret(self, client_key, token, request):
+        return request.token.secret
+
     def get_access_token_secret(self, client_key, token, request):
         return request.token.secret
 
     def get_default_realms(self, client_key, request):
         return ['API']
 
+    def validate_request_token(self, client_key, token, request):
+        try:
+            token = Token.objects.get(
+                token_type=Token.REQUEST,
+                consumer__key=client_key,
+                key=token,
+                is_approved=True,
+            )
+        except Token.DoesNotExist:
+            return False
+        else:
+            request.token = token
+            return True
+
     def validate_access_token(self, client_key, token, request):
         try:
             token = Token.objects.get(
@@ -76,6 +95,9 @@ class PistonRequestValidator(RequestValidator):
     def validate_redirect_uri(self, *args, **kwargs):
         return True
 
+    def validate_verifier(self, client_key, token, verifier, request):
+        return True
+
     def get_client_secret(self, client_key, request):
         return request.oauth_consumer.secret
 
@@ -88,6 +110,16 @@ class PistonRequestValidator(RequestValidator):
             consumer=request.oauth_consumer,
         )
 
+    def save_access_token(self, token, request):
+        Token.objects.create(
+            token_type=Token.ACCESS,
+            timestamp=request.timestamp,
+            key=token['oauth_token'],
+            secret=token['oauth_token_secret'],
+            consumer=request.oauth_consumer,
+            user=request.token.user,
+        )
+
     def verify_request_token(self, token, request):
         return Token.objects.filter(
             token_type=Token.REQUEST, key=token, is_approved=False
@@ -108,3 +140,10 @@ class PistonRequestValidator(RequestValidator):
 
     def get_redirect_uri(self, token, request):
         return request.redirect_uri
+
+    def invalidate_request_token(self, client_key, request_token, request):
+        Token.objects.filter(
+            token_type=Token.REQUEST,
+            key=request_token,
+            consumer__key=client_key,
+        )
index ee3d66e..c8e07d2 100644 (file)
@@ -45,7 +45,7 @@ class ApiTest(TestCase):
         with open(filename) as f:
             good_content = f.read().rstrip()
         self.assertEqual(content, good_content, content)
-    
+
     def assert_json_response(self, url, name):
         data = self.load_json(url)
         filename = path.join(path.dirname(__file__), 'res', 'responses', name)
index 5936e1b..8f99141 100644 (file)
@@ -5,7 +5,6 @@
 from django.conf.urls import url, include
 from django.views.decorators.csrf import csrf_exempt
 from django.views.generic import TemplateView
-from piston.authentication import oauth_access_token
 import catalogue.views
 from api import handlers
 from api.piston_patch import oauth_user_auth
@@ -15,7 +14,7 @@ from . import views
 urlpatterns = [
     url(r'^oauth/request_token/$', views.OAuth1RequestTokenView.as_view()),
     url(r'^oauth/authorize/$', oauth_user_auth, name='oauth_user_auth'),
-    url(r'^oauth/access_token/$', csrf_exempt(oauth_access_token)),
+    url(r'^oauth/access_token/$', csrf_exempt(views.OAuth1AccessTokenView.as_view())),
 
     url(r'^$', TemplateView.as_view(template_name='api/main.html'), name='api'),
 
index 3cf957e..518445d 100644 (file)
@@ -3,8 +3,9 @@
 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 #
 from django.http import Http404
+from django.views.generic.base import View
 from oauthlib.common import urlencode
-from oauthlib.oauth1 import RequestTokenEndpoint
+from oauthlib.oauth1 import RequestTokenEndpoint, AccessTokenEndpoint
 from piston.models import KEY_SIZE, SECRET_SIZE
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
@@ -34,7 +35,7 @@ class OAuth1RequestTokenEndpoint(RequestTokenEndpoint):
         return urlencode(token.items())
 
 
-class OAuth1RequestTokenView(APIView):
+class OAuth1RequestTokenView(View):
     def __init__(self):
         self.endpoint = OAuth1RequestTokenEndpoint(PistonRequestValidator())
 
@@ -46,6 +47,37 @@ class OAuth1RequestTokenView(APIView):
         )
 
 
+class OAuth1AccessTokenEndpoint(AccessTokenEndpoint):
+    def _create_request(self, *args, **kwargs):
+        r = super(OAuth1AccessTokenEndpoint, self)._create_request(*args, **kwargs)
+        r.verifier = 'x' * 20
+        return r
+
+    def create_access_token(self, request, credentials):
+        request.realms = self.request_validator.get_realms(
+            request.resource_owner_key, request)
+        token = {
+            'oauth_token': self.token_generator()[:KEY_SIZE],
+            'oauth_token_secret': self.token_generator()[:SECRET_SIZE],
+            'oauth_authorized_realms': ' '.join(request.realms)
+        }
+        token.update(credentials)
+        self.request_validator.save_access_token(token, request)
+        return urlencode(token.items())
+
+
+class OAuth1AccessTokenView(View):
+    def __init__(self):
+        self.endpoint = OAuth1AccessTokenEndpoint(PistonRequestValidator())
+
+    def dispatch(self, request):
+        return oauthlib_response(
+            self.endpoint.create_access_token_response(
+                **oauthlib_request(request)
+            )
+        )
+
+
 class UserView(RetrieveAPIView):
     permission_classes = [IsAuthenticated]
     serializer_class = serializers.UserSerializer