www-bocal/api/views.py

96 lines
3.1 KiB
Python
Raw Normal View History

import datetime
import json
2017-09-24 00:42:36 +02:00
from django.core.exceptions import ValidationError
from django.http import response
2017-09-24 18:20:10 +02:00
from django.views.decorators.csrf import csrf_exempt
2017-09-23 21:40:45 +02:00
2017-09-24 00:42:36 +02:00
import mainsite.models as mainModels
from . import models
2017-09-24 00:42:36 +02:00
2017-09-24 18:20:10 +02:00
def authentify(data, payload):
"""returns whether the request's authentification is correct"""
required = ["keyId", "timestamp", "hmac"]
2017-09-24 00:42:36 +02:00
for field in required:
if field not in data:
return response.HttpResponseForbidden(
'Missing required field "{}"'.format(field)
)
2017-09-24 00:42:36 +02:00
try:
key = models.ApiKey.objects.get(id=data["keyId"])
2017-09-24 00:42:36 +02:00
except models.ApiKey.DoesNotExist:
return response.HttpResponseForbidden("Bad authentication")
2017-09-24 00:42:36 +02:00
if not key.isCorrect(data["timestamp"], data["hmac"], payload):
return response.HttpResponseForbidden("Bad authentication")
2017-09-24 00:42:36 +02:00
2017-09-24 18:20:10 +02:00
def apiView(required=[]):
def decorator(fct):
@csrf_exempt
def wrap(request, *args, **kwargs):
try:
data = json.loads(request.body.decode("utf-8"))
except TypeError:
return response.HttpResponseBadRequest("Bad packet format")
except json.decoder.JSONDecodeError:
2017-09-24 18:20:10 +02:00
return response.HttpResponseBadRequest("Bad json")
2017-09-24 00:42:36 +02:00
2017-09-24 18:20:10 +02:00
try:
authData = data["auth"]
reqDataOrig = data["req"]
2017-09-24 18:20:10 +02:00
except KeyError:
return response.HttpResponseBadRequest("Bad request format")
2017-09-24 00:42:36 +02:00
try:
reqData = json.loads(reqDataOrig)
except TypeError:
return response.HttpResponseBadRequest("Bad packet format")
except json.decoder.JSONDecodeError:
return response.HttpResponseBadRequest("Bad inner json")
2017-09-24 18:20:10 +02:00
for field in required:
if field not in reqData:
return response.HttpResponseBadRequest(
"Missing field {}".format(field)
)
2017-09-24 00:42:36 +02:00
authVal = authentify(authData, reqDataOrig)
2017-09-24 18:20:10 +02:00
if authVal is not None:
return authVal
2017-09-24 00:42:36 +02:00
2017-09-24 18:20:10 +02:00
return fct(request, reqData, *args, **kwargs)
2017-09-24 18:20:10 +02:00
return wrap
2017-09-24 18:20:10 +02:00
return decorator
2017-09-24 00:42:36 +02:00
@apiView(required=["id", "url", "date"])
def publishApiView(request, data):
"""Publish a BOcal, and create the corresponding year if needed"""
if mainModels.Publication.objects.filter(num=data["id"]).count() > 0:
2017-09-24 00:42:36 +02:00
return response.HttpResponseBadRequest(
"Un BOcal du même numéro est déjà présent ! Ajoutez celui-ci à la "
"main si vous voulez vraiment faire ça."
)
2017-09-24 00:42:36 +02:00
try:
year, month, day = [int(x) for x in data["date"].split("-")]
2017-09-24 00:42:36 +02:00
date = datetime.date(year, month, day)
except Exception:
2017-09-24 00:42:36 +02:00
return response.HttpResponseBadRequest("Bad date")
pub = mainModels.Publication(num=data["id"], url=data["url"], date=date)
2017-09-24 00:42:36 +02:00
try:
pub.full_clean()
except ValidationError as e:
return response.HttpResponseBadRequest("Invalid data: {}".format(e))
2017-09-24 00:42:36 +02:00
pub.save()
pub.createPubYear()
2017-09-24 00:42:36 +02:00
return response.HttpResponse("OK")