1 # -*- coding: utf-8 -*-
 
   2 # This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
 
   3 # Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
 
   5 from django.http import Http404
 
   6 from django.views.generic.base import View
 
   7 from oauthlib.common import urlencode
 
   8 from oauthlib.oauth1 import RequestTokenEndpoint, AccessTokenEndpoint
 
   9 from api.piston.models import KEY_SIZE, SECRET_SIZE
 
  10 from rest_framework.permissions import IsAuthenticated
 
  11 from rest_framework.response import Response
 
  12 from rest_framework.views import APIView
 
  13 from rest_framework.generics import ListAPIView, RetrieveAPIView, get_object_or_404
 
  14 from migdal.models import Entry
 
  15 from catalogue.models import Book
 
  16 from .models import BookUserData
 
  17 from . import serializers
 
  18 from .request_validator import PistonRequestValidator
 
  19 from .utils import oauthlib_request, oauthlib_response, vary_on_auth
 
  22 class OAuth1RequestTokenEndpoint(RequestTokenEndpoint):
 
  23     def _create_request(self, *args, **kwargs):
 
  24         r = super(OAuth1RequestTokenEndpoint, self)._create_request(*args, **kwargs)
 
  25         r.redirect_uri = 'oob'
 
  28     def create_request_token(self, request, credentials):
 
  30             'oauth_token': self.token_generator()[:KEY_SIZE],
 
  31             'oauth_token_secret': self.token_generator()[:SECRET_SIZE],
 
  33         token.update(credentials)
 
  34         self.request_validator.save_request_token(token, request)
 
  35         return urlencode(token.items())
 
  39 class OAuth1RequestTokenView(View):
 
  41         self.endpoint = OAuth1RequestTokenEndpoint(PistonRequestValidator())
 
  43     def dispatch(self, request):
 
  44         return oauthlib_response(
 
  45             self.endpoint.create_request_token_response(
 
  46                 **oauthlib_request(request)
 
  51 class OAuth1AccessTokenEndpoint(AccessTokenEndpoint):
 
  52     def _create_request(self, *args, **kwargs):
 
  53         r = super(OAuth1AccessTokenEndpoint, self)._create_request(*args, **kwargs)
 
  57     def create_access_token(self, request, credentials):
 
  58         request.realms = self.request_validator.get_realms(
 
  59             request.resource_owner_key, request)
 
  61             'oauth_token': self.token_generator()[:KEY_SIZE],
 
  62             'oauth_token_secret': self.token_generator()[:SECRET_SIZE],
 
  63             'oauth_authorized_realms': ' '.join(request.realms)
 
  65         token.update(credentials)
 
  66         self.request_validator.save_access_token(token, request)
 
  67         return urlencode(token.items())
 
  71 class OAuth1AccessTokenView(View):
 
  73         self.endpoint = OAuth1AccessTokenEndpoint(PistonRequestValidator())
 
  75     def dispatch(self, request):
 
  76         return oauthlib_response(
 
  77             self.endpoint.create_access_token_response(
 
  78                 **oauthlib_request(request)
 
  84 class UserView(RetrieveAPIView):
 
  85     permission_classes = [IsAuthenticated]
 
  86     serializer_class = serializers.UserSerializer
 
  89         return self.request.user
 
  93 class BookUserDataView(RetrieveAPIView):
 
  94     permission_classes = [IsAuthenticated]
 
  95     serializer_class = serializers.BookUserDataSerializer
 
  96     lookup_field = 'book__slug'
 
  97     lookup_url_kwarg = 'slug'
 
  99     def get_queryset(self):
 
 100         return BookUserData.objects.filter(user=self.request.user)
 
 102     def get(self, *args, **kwargs):
 
 104             return super(BookUserDataView, self).get(*args, **kwargs)
 
 106             return Response({"state": "not_started"})
 
 108     def post(self, request, slug, state):
 
 109         if state not in ('reading', 'complete'):
 
 112         book = get_object_or_404(Book, slug=slug)
 
 113         instance = BookUserData.update(book, request.user, state)
 
 114         serializer = self.get_serializer(instance)
 
 115         return Response(serializer.data)
 
 118 class BlogView(ListAPIView):
 
 119     serializer_class = serializers.BlogSerializer
 
 121     def get_queryset(self):
 
 122         after = self.request.query_params.get('after')
 
 123         count = int(self.request.query_params.get('count', 20))
 
 124         entries = Entry.published_objects.filter(in_stream=True).order_by('-first_published_at')
 
 126             entries = entries.filter(first_published_at__lt=after)
 
 128             entries = entries[:count]