Merge branch 'master' into django-1.10
[mygpo.git] / mygpo / api / __init__.py
blob0bff19efd56335bc1f09e1e51929b77fc25f5873
1 from datetime import datetime
3 from django.core.exceptions import ObjectDoesNotExist
4 from django.http import HttpResponseBadRequest, HttpResponseNotFound
5 from django.views.decorators.csrf import csrf_exempt
6 from django.views.decorators.cache import never_cache
7 from django.utils.decorators import method_decorator
8 from django.views import View
10 from mygpo.utils import parse_request_body
11 from mygpo.api.exceptions import ParameterMissing
12 from mygpo.decorators import cors_origin
13 from mygpo.api.basic_auth import require_valid_user, check_username
16 import logging
17 logger = logging.getLogger(__name__)
20 class RequestException(Exception):
21 """ Raised if the request is malfored or otherwise invalid """
24 class APIView(View):
26 @method_decorator(csrf_exempt)
27 @method_decorator(require_valid_user)
28 @method_decorator(check_username)
29 @method_decorator(never_cache)
30 @method_decorator(cors_origin())
31 def dispatch(self, *args, **kwargs):
32 """ Dispatches request and does generic error handling """
33 try:
34 return super(APIView, self).dispatch(*args, **kwargs)
36 except ObjectDoesNotExist as e:
37 return HttpResponseNotFound(str(e))
39 except (RequestException, ParameterMissing) as e:
40 return HttpResponseBadRequest(str(e))
42 def parsed_body(self, request):
43 """ Returns the object parsed from the JSON request body """
45 if not request.body:
46 raise RequestException('POST data must not be empty')
48 try:
49 # TODO: implementation of parse_request_body can be moved here
50 # after all views using it have been refactored
51 return parse_request_body(request)
52 except (UnicodeDecodeError, ValueError) as e:
53 msg = 'Could not decode request body for user {}: {}'.format(
54 request.user.username,
55 request.body.decode('ascii', errors='replace'))
56 logger.warn(msg, exc_info=True)
57 raise RequestException(msg)
59 def get_since(self, request):
60 """ Returns parsed "since" GET parameter """
61 since_ = request.GET.get('since', None)
63 if since_ is None:
64 raise RequestException("parameter 'since' missing")
66 try:
67 since_ = int(since_)
68 since = datetime.fromtimestamp(since_)
69 except ValueError:
70 raise RequestException("'since' is not a valid timestamp")
72 if since_ < 0:
73 raise RequestException("'since' must be a non-negative number")
75 return since