Refactor the Micropub error responses into a non-view module, have them produce an immediately raise-able exception

This commit is contained in:
Danielle McLean 2018-07-03 10:03:35 +10:00
parent 065619772e
commit d68dda85ad
Signed by untrusted user: 00dani
GPG key ID: 8EB789DDF3ABD240
9 changed files with 69 additions and 73 deletions

36
micropub/error.py Normal file
View file

@ -0,0 +1,36 @@
from django.http import JsonResponse
from lemoncurry.middleware import ResponseException
from typing import Optional
def forbidden() -> ResponseException:
return res('forbidden', 403)
def unauthorized() -> ResponseException:
return res('unauthorized', 401)
def bad_req(msg: str) -> ResponseException:
return res('invalid_request', msg=msg)
def bad_type(type: str) -> ResponseException:
msg = 'unsupported request type {0}'.format(type)
return res('invalid_request', 415, msg)
def bad_scope(scope: str) -> ResponseException:
return res('insufficient_scope', 401, scope=scope)
def res(error: str,
status: Optional[int]=400,
msg: Optional[str]=None,
scope: Optional[str]=None):
content = {'error': error}
if msg is not None:
content['error_description'] = msg
if scope:
content['scope'] = scope
return ResponseException(JsonResponse(content, status=status))

View file

@ -26,6 +26,6 @@ def micropub(request):
if request.content_type == 'application/json':
request.json = json.load(request)
action = request.json.get('action', 'create')
if action in actions:
return actions[action](request)
return error.bad_req('unknown action: {}'.format(action))
if action not in actions:
raise error.bad_req('unknown action: {}'.format(action))
return actions[action](request)

View file

@ -7,7 +7,7 @@ from entries.models import Cat, Entry
from entries.kinds import Article, Note, Reply, Like, Repost
from lemoncurry import utils
from . import error
from .. import error
def form_to_mf2(request):
@ -33,14 +33,14 @@ def create(request):
'application/x-www-form-urlencoded': form_to_mf2,
}
if 'create' not in request.token:
return error.bad_scope('create')
raise error.bad_scope('create')
if request.content_type not in normalise:
return error.unsupported_type(request.content_type)
raise error.unsupported_type(request.content_type)
body = normalise[request.content_type](request)
if 'type' not in body:
return error.bad_req('mf2 object type required')
raise error.bad_req('mf2 object type required')
if body['type'] != ['h-entry']:
return error.bad_req('only h-entry supported')
raise error.bad_req('only h-entry supported')
entry = Entry(author=request.token.user)
props = body.get('properties', {})

View file

@ -4,7 +4,7 @@ from ronkyuu import webmention
from entries.from_url import from_url
from entries.jobs import ping_hub, send_mentions
from . import error
from .. import error
def delete(request):
normalise = {
@ -12,14 +12,14 @@ def delete(request):
'application/x-www-form-urlencoded': lambda r: r.POST.get('url'),
}
if 'delete' not in request.token:
return error.bad_scope('delete')
raise error.bad_scope('delete')
if request.content_type not in normalise:
return error.unsupported_type(request.content_type)
raise error.unsupported_type(request.content_type)
url = normalise[request.content_type](request)
entry = from_url(url)
if entry.author != request.token.user:
return error.forbid('entry belongs to another user')
raise error.forbid('entry belongs to another user')
perma = entry.absolute_url
pings = entry.affected_urls

View file

@ -1,31 +0,0 @@
from django.http import JsonResponse
def forbidden():
return res('forbidden', 403)
def unauthorized():
return res('unauthorized', 401)
def bad_req(msg):
return res('invalid_request', msg=msg)
def bad_type(type):
msg = 'unsupported request type {0}'.format(type)
return res('invalid_request', 415, msg)
def bad_scope(scope):
return res('insufficient_scope', 401, scope=scope)
def res(error, status=400, msg=None, scope=None):
content = {'error': error}
if msg:
content['error_description'] = msg
if scope:
content['scope'] = scope
return JsonResponse(content, status=status)

View file

@ -8,7 +8,7 @@ import magic
from lemonauth import tokens
from lemoncurry.utils import absolute_url
from . import error
from .. import error
ACCEPTED_MEDIA_TYPES = (
'image/gif',
@ -22,12 +22,12 @@ ACCEPTED_MEDIA_TYPES = (
def media(request):
token = tokens.auth(request)
if 'file' not in request.FILES:
return error.bad_req(
raise error.bad_req(
"a file named 'file' must be provided to the media endpoint"
)
file = request.FILES['file']
if file.content_type not in ACCEPTED_MEDIA_TYPES:
return error.bad_req(
raise error.bad_req(
'unacceptable file type {0}'.format(file.content_type)
)
@ -39,7 +39,7 @@ def media(request):
sha.update(chunk)
if mime != file.content_type:
return error.bad_req(
raise error.bad_req(
'detected file type {0} did not match specified file type {1}'
.format(mime, file.content_type)
)

View file

@ -1,9 +1,8 @@
from django.http import JsonResponse
from django.urls import reverse
from lemoncurry import requests
from lemoncurry.middleware import ResponseException
from lemoncurry.utils import absolute_url
from . import error
from .. import error
def config(request):
@ -15,12 +14,10 @@ def config(request):
def source(request):
get = request.GET
if 'url' not in get:
raise ResponseException(error.bad_req(
'must specify url parameter for source query'
))
raise error.bad_req('must specify url parameter for source query')
mf2 = requests.mf2(get['url']).to_dict(filter_by_type='h-entry')
if not mf2:
raise ResponseException(error.bad_req('no h-entry at the requested url'))
raise error.bad_req('no h-entry at the requested url')
entry = mf2[0]
keys = get.getlist('properties', []) + get.getlist('properties[]', [])
if not keys:
@ -43,9 +40,9 @@ queries = {
def query(request):
if 'q' not in request.GET:
return error.bad_req('must specify q parameter')
raise error.bad_req('must specify q parameter')
q = request.GET['q']
if q not in queries:
return error.bad_req('unsupported query {0}'.format(q))
raise error.bad_req('unsupported query {0}'.format(q))
res = queries[q](request)
return JsonResponse(res)