from django.http import response from django.core.exceptions import ValidationError from django.views.decorators.csrf import csrf_exempt import json import datetime from . import models import mainsite.models as mainModels def authentify(data, payload): ''' returns whether the request's authentification is correct ''' required = ['keyId', 'timestamp', 'hmac'] for field in required: if field not in data: return response.HttpResponseForbidden( 'Missing required field "{}"'.format(field)) try: key = models.ApiKey.objects.get(id=data['keyId']) except models.ApiKey.DoesNotExist: return response.HttpResponseForbidden('Bad authentication') if not key.isCorrect(data['timestamp'], data['hmac'], payload): return response.HttpResponseForbidden('Bad authentication') 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: return response.HttpResponseBadRequest("Bad json") try: authData = data['auth'] reqDataOrig = data['req'] except KeyError: return response.HttpResponseBadRequest("Bad request format") try: reqData = json.loads(reqDataOrig) except TypeError: return response.HttpResponseBadRequest("Bad packet format") except json.decoder.JSONDecodeError: return response.HttpResponseBadRequest("Bad inner json") for field in required: if field not in reqData: return response.HttpResponseBadRequest( "Missing field {}".format(field)) authVal = authentify(authData, reqDataOrig) if authVal is not None: return authVal return fct(request, reqData, *args, **kwargs) return wrap return decorator @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: 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.") try: year, month, day = [int(x) for x in data['date'].split('-')] date = datetime.date(year, month, day) except: return response.HttpResponseBadRequest("Bad date") pub = mainModels.Publication(num=data['id'], url=data['url'], date=date) try: pub.full_clean() except ValidationError as e: return response.HttpResponseBadRequest( "Invalid data: {}".format(e)) pub.save() pub.createPubYear() return response.HttpResponse("OK")