6d462fa3a0af60b39c81060c37e8986bc67f80f7
[wolnelektury.git] / src / api / views.py
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.
4 #
5 from django.http import Http404, HttpResponse
6 from oauthlib.common import urlencode
7 from oauthlib.oauth1 import RequestTokenEndpoint
8 from piston.models import KEY_SIZE, SECRET_SIZE
9 from rest_framework.permissions import IsAuthenticated
10 from rest_framework.response import Response
11 from rest_framework.views import APIView
12 from rest_framework.generics import ListAPIView, RetrieveAPIView, get_object_or_404
13 from migdal.models import Entry
14 from catalogue.models import Book
15 from .models import BookUserData
16 from . import serializers
17 from .request_validator import PistonRequestValidator
18
19
20 class OAuth1RequestTokenEndpoint(RequestTokenEndpoint):
21     def _create_request(self, *args, **kwargs):
22         r = super(OAuth1RequestTokenEndpoint, self)._create_request(*args, **kwargs)
23         r.redirect_uri = 'oob'
24         return r
25
26     def create_request_token(self, request, credentials):
27         token = {
28             'oauth_token': self.token_generator()[:KEY_SIZE],
29             'oauth_token_secret': self.token_generator()[:SECRET_SIZE],
30         }
31         token.update(credentials)
32         self.request_validator.save_request_token(token, request)
33         return urlencode(token.items())
34
35
36 class OAuth1RequestTokenView(APIView):
37     def __init__(self):
38         self.endpoint = OAuth1RequestTokenEndpoint(PistonRequestValidator())
39     def dispatch(self, request):
40         headers, body, status = self.endpoint.create_request_token_response(
41             request.build_absolute_uri(),
42             request.method,
43             request.body,
44             {
45                 "Authorization": request.META['HTTP_AUTHORIZATION']
46             } if 'HTTP_AUTHORIZATION' in request.META else None
47         )
48
49         response = HttpResponse(body, status=status)
50         for k, v in headers.items():
51             response[k] = v
52         return response
53
54
55 class UserView(RetrieveAPIView):
56     permission_classes = [IsAuthenticated]
57     serializer_class = serializers.UserSerializer
58
59     def get_object(self):
60         return self.request.user
61
62
63 class BookUserDataView(RetrieveAPIView):
64     permission_classes = [IsAuthenticated]
65     serializer_class = serializers.BookUserDataSerializer
66     lookup_field = 'book__slug'
67     lookup_url_kwarg = 'slug'
68
69     def get_queryset(self):
70         return BookUserData.objects.filter(user=self.request.user)
71
72     def get(self, *args, **kwargs):
73         try:
74             return super(BookUserDataView, self).get(*args, **kwargs)
75         except Http404:
76             return Response({"state": "not_started"})
77
78     def post(self, request, slug, state):
79         if state not in ('reading', 'complete'):
80             raise Http404
81
82         book = get_object_or_404(Book, slug=slug)
83         instance = BookUserData.update(book, request.user, state)
84         serializer = self.get_serializer(instance)
85         return Response(serializer.data)
86
87
88 class BlogView(ListAPIView):
89     serializer_class = serializers.BlogSerializer
90
91     def get_queryset(self):
92         after = self.request.query_params.get('after')
93         count = int(self.request.query_params.get('count', 20))
94         entries = Entry.published_objects.filter(in_stream=True).order_by('-first_published_at')
95         if after:
96             entries = entries.filter(first_published_at__lt=after)
97         if count:
98             entries = entries[:count]
99         return entries