Enable support for deleting entries through Micropub :D

This commit is contained in:
Danielle McLean 2018-07-02 15:08:13 +10:00
parent 427dcde672
commit fa8419976d
Signed by untrusted user: 00dani
GPG key ID: 8EB789DDF3ABD240
4 changed files with 84 additions and 13 deletions

View file

@ -146,6 +146,24 @@ class Entry(ModelMeta, TimeStampedModel):
base = 'https://' + DjangoSite.objects.get_current().domain
return urljoin(base, self.url)
@property
def affected_urls(self):
base = 'https://' + DjangoSite.objects.get_current().domain
kind = kinds.from_id[self.kind]
urls = {
self.url,
reverse('entries:index', kwargs={'kind': kind}),
reverse('entries:atom_by_kind', kwargs={'kind': kind}),
reverse('entries:rss_by_kind', kwargs={'kind': kind}),
} | {cat.url for cat in self.cats.all()}
if kind.on_home:
urls |= {
reverse('home:index'),
reverse('entries:atom'),
reverse('entries:rss')
}
return {urljoin(base, u) for u in urls}
@property
def url(self):
kind = kinds.from_id[self.kind]

View file

@ -1,11 +1,19 @@
import json
from django.views.decorators.csrf import csrf_exempt
from django.views.decorators.http import require_http_methods
from lemonauth import tokens
from .create import create
from .delete import delete
from .query import query
actions = {
'create': create,
'delete': delete,
}
@csrf_exempt
@require_http_methods(['GET', 'HEAD', 'POST'])
@ -14,7 +22,13 @@ def micropub(request):
if hasattr(token, 'content'):
return token
request.token = token
if request.method == 'POST':
return create(request)
if request.method in ('GET', 'HEAD'):
return query(request)
action = request.POST.get('action', 'create')
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))

View file

@ -1,4 +1,3 @@
import json
from django.urls import reverse
from django.http import HttpResponse
from urllib.parse import urljoin
@ -30,7 +29,7 @@ def form_to_mf2(request):
def create(request):
normalise = {
'application/json': json.load,
'application/json': lambda r: r.json,
'application/x-www-form-urlencoded': form_to_mf2,
}
if 'create' not in request.token:
@ -77,15 +76,7 @@ def create(request):
base = utils.origin(request)
perma = urljoin(base, entry.url)
short = urljoin(base, entry.short_url)
others = [urljoin(base, url) for url in (
reverse('home:index'),
reverse('entries:atom'),
reverse('entries:rss'),
reverse('entries:index', kwargs={'kind': kind}),
reverse('entries:atom_by_kind', kwargs={'kind': kind}),
reverse('entries:rss_by_kind', kwargs={'kind': kind}),
)] + [urljoin(base, cat.url) for cat in cats]
ping_hub.delay(perma, *others)
ping_hub.delay(*entry.affected_urls)
send_mentions.delay(perma)
res = HttpResponse(status=201)

48
micropub/views/delete.py Normal file
View file

@ -0,0 +1,48 @@
from django.http import HttpResponse
from django.urls import resolve, Resolver404
from urllib.parse import urlparse
from entries.jobs import ping_hub
from entries.models import Entry
from . import error
def delete(request):
normalise = {
'application/json': lambda r: r.json.get('url'),
'application/x-www-form-urlencoded': lambda r: r.POST.get('url'),
}
if 'delete' not in request.token:
return error.bad_scope('delete')
if request.content_type not in normalise:
return error.unsupported_type(request.content_type)
url = normalise[request.content_type](request)
if not url:
return error.bad_req('url parameter required')
if '//' not in url:
url = '//' + url
url = urlparse(url, scheme='https')
if url.scheme not in ('http', 'https') or url.netloc != request.site.domain:
return error.bad_req('url does not point to this site')
try:
match = resolve(url.path)
except Resolver404:
return error.bad_req('url does not point to a valid page on this site')
if match.view_name != 'entries:entry':
return error.bad_req('url does not point to an entry on this site')
try:
entry = Entry.objects.get(pk=match.kwargs['id'])
except Entry.DoesNotExist:
return error.bad_req('url does not point to an existing entry')
if entry.author != request.token.user:
return error.forbid('entry belongs to another user')
urls = entry.affected_urls
entry.delete()
ping_hub.delay(urls)
return HttpResponse(status=204)