From: Stefan Koegl Date: Thu, 16 Sep 2010 12:33:26 +0000 (+0300) Subject: @allowed_methods to check for correct HTTP method X-Git-Url: https://repo.or.cz/w/mygpo.git/commitdiff_plain/dec2816fcc0930c2aa06758328e155c6ad2bea11 @allowed_methods to check for correct HTTP method --- diff --git a/mygpo/api/advanced/__init__.py b/mygpo/api/advanced/__init__.py index 83fcaf8a..902399d6 100644 --- a/mygpo/api/advanced/__init__.py +++ b/mygpo/api/advanced/__init__.py @@ -16,7 +16,7 @@ # from mygpo.api.basic_auth import require_valid_user, check_username -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404, HttpResponseNotAllowed +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404 from mygpo.api.models import Device, Podcast, SubscriptionAction, Episode, EpisodeAction, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION, EPISODE_ACTION_TYPES, DEVICE_TYPES, Subscription from mygpo.api.models.users import EpisodeFavorite from mygpo.api.httpresponse import JsonResponse @@ -30,6 +30,7 @@ from datetime import datetime, timedelta import dateutil.parser from mygpo.log import log from mygpo.utils import parse_time, parse_bool +from mygpo.decorators import allowed_methods from django.db import IntegrityError import re from django.views.decorators.csrf import csrf_exempt @@ -51,6 +52,7 @@ except ImportError: @csrf_exempt @require_valid_user @check_username +@allowed_methods(['GET', 'POST']) def subscriptions(request, username, device_uid): now = datetime.now() @@ -94,9 +96,6 @@ def subscriptions(request, username, device_uid): 'update_urls': update_urls, }) - else: - return HttpResponseNotAllowed(['GET', 'POST']) - def update_subscriptions(user, device, add, remove): updated_urls = [] @@ -156,6 +155,7 @@ def get_subscription_changes(user, device, since, until): @csrf_exempt @require_valid_user @check_username +@allowed_methods(['GET', 'POST']) def episodes(request, username, version=1): version = int(version) @@ -193,9 +193,6 @@ def episodes(request, username, version=1): return JsonResponse(get_episode_changes(request.user, podcast, device, since, now, aggregated, version)) - else: - return HttpResponseNotAllowed(['POST', 'GET']) - def get_episode_changes(user, podcast, device, since, until, aggregated, version): if aggregated: @@ -325,34 +322,32 @@ def update_episodes(user, actions): @csrf_exempt @require_valid_user @check_username +# Workaround for mygpoclient 1.0: It uses "PUT" requests +# instead of "POST" requests for uploading device settings +@allowed_methods(['POST', 'PUT']) def device(request, username, device_uid): - # Workaround for mygpoclient 1.0: It uses "PUT" requests - # instead of "POST" requests for uploading device settings - if request.method in ('POST', 'PUT'): - d, created = Device.objects.get_or_create(user=request.user, uid=device_uid) + d, created = Device.objects.get_or_create(user=request.user, uid=device_uid) - #undelete a previously deleted device - if d.deleted: - d.deleted = False - d.save() + #undelete a previously deleted device + if d.deleted: + d.deleted = False + d.save() - data = json.loads(request.raw_post_data) + data = json.loads(request.raw_post_data) - if 'caption' in data: - d.name = data['caption'] + if 'caption' in data: + d.name = data['caption'] - if 'type' in data: - if not valid_devicetype(data['type']): - return HttpResponseBadRequest('invalid device type %s' % data['type']) - d.type = data['type'] + if 'type' in data: + if not valid_devicetype(data['type']): + return HttpResponseBadRequest('invalid device type %s' % data['type']) + d.type = data['type'] - d.save() + d.save() - return HttpResponse() + return HttpResponse() - else: - return HttpResponseNotAllowed(['POST']) def valid_devicetype(type): for t in DEVICE_TYPES: @@ -370,22 +365,18 @@ def valid_episodeaction(type): @csrf_exempt @require_valid_user @check_username +@allowed_methods(['GET']) def devices(request, username): - - if request.method == 'GET': - devices = [] - for d in Device.objects.filter(user=request.user, deleted=False): - devices.append({ - 'id': d.uid, - 'caption': d.name, - 'type': d.type, - 'subscriptions': Subscription.objects.filter(device=d).count() - }) - - return JsonResponse(devices) - - else: - return HttpResponseNotAllowed(['GET']) + devices = [] + for d in Device.objects.filter(user=request.user, deleted=False): + devices.append({ + 'id': d.uid, + 'caption': d.name, + 'type': d.type, + 'subscriptions': Subscription.objects.filter(device=d).count() + }) + + return JsonResponse(devices) @csrf_exempt diff --git a/mygpo/api/advanced/auth.py b/mygpo/api/advanced/auth.py index 8ba2d73c..1571133c 100644 --- a/mygpo/api/advanced/auth.py +++ b/mygpo/api/advanced/auth.py @@ -18,7 +18,7 @@ from django.contrib.auth.models import User from mygpo.api.basic_auth import require_valid_user, check_username from django.contrib import auth -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404, HttpResponseNotAllowed +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404 from mygpo.api.httpresponse import JsonResponse from mygpo.web.models import SecurityToken from django.shortcuts import get_object_or_404 diff --git a/mygpo/api/advanced/directory.py b/mygpo/api/advanced/directory.py index 28f0d155..ffe1b046 100644 --- a/mygpo/api/advanced/directory.py +++ b/mygpo/api/advanced/directory.py @@ -16,7 +16,7 @@ # from mygpo.api.basic_auth import require_valid_user, check_username -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404, HttpResponseNotAllowed +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404 from mygpo.api.httpresponse import JsonResponse from mygpo.exceptions import ParameterMissing from django.shortcuts import get_object_or_404 diff --git a/mygpo/api/advanced/episode.py b/mygpo/api/advanced/episode.py index 7c5236d5..9e03b326 100644 --- a/mygpo/api/advanced/episode.py +++ b/mygpo/api/advanced/episode.py @@ -16,7 +16,7 @@ # from mygpo.api.basic_auth import require_valid_user, check_username -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404, HttpResponseNotAllowed +from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden, Http404 from mygpo.api.httpresponse import JsonResponse from mygpo.exceptions import ParameterMissing from django.shortcuts import get_object_or_404 @@ -27,6 +27,7 @@ from django.utils.translation import ugettext as _ from datetime import datetime, timedelta from mygpo.log import log from mygpo.utils import parse_time +from mygpo.decorators import allowed_methods import dateutil.parser from django.views.decorators.csrf import csrf_exempt @@ -47,6 +48,7 @@ except ImportError: @csrf_exempt @require_valid_user @check_username +@allowed_methods(['POST', 'GET']) def chapters(request, username): now = datetime.now() @@ -124,10 +126,6 @@ def chapters(request, username): 'timestamp': now_ }) - else: - return HttpResponseNotAllowed(['GET', 'POST']) - - def update_chapters(req, user): podcast, c = Podcast.objects.get_or_create(url=req['podcast']) diff --git a/mygpo/api/advanced/settings.py b/mygpo/api/advanced/settings.py index 946571e1..d7af6793 100644 --- a/mygpo/api/advanced/settings.py +++ b/mygpo/api/advanced/settings.py @@ -16,17 +16,19 @@ # from mygpo.api.basic_auth import require_valid_user, check_username -from django.http import HttpResponseBadRequest, HttpResponseNotAllowed +from django.http import HttpResponseBadRequest from mygpo.api.httpresponse import JsonResponse from django.shortcuts import get_object_or_404 from mygpo.api.models import Device, UserProfile, SubscriptionMeta, EpisodeSettings from django.views.decorators.csrf import csrf_exempt +from mygpo.decorators import allowed_methods import json @csrf_exempt @require_valid_user @check_username +@allowed_methods(['GET', 'POST']) def main(request, username, scope): models = dict( @@ -50,9 +52,6 @@ def main(request, username, scope): actions = json.loads(request.raw_post_data) return JsonResponse( update_settings(obj, actions) ) - else: - return HttpResponseNotAllowed(['GET', 'POST']) - def update_settings(obj, actions): for key, value in actions.get('set', {}).iteritems(): diff --git a/mygpo/api/simple.py b/mygpo/api/simple.py index 2b58d6b1..d396967d 100644 --- a/mygpo/api/simple.py +++ b/mygpo/api/simple.py @@ -16,7 +16,7 @@ # from mygpo.api.basic_auth import require_valid_user, check_username -from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed +from django.http import HttpResponse, HttpResponseBadRequest from mygpo.api.models import Device, SubscriptionAction, Podcast, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION, SuggestionEntry from mygpo.api.opml import Exporter, Importer from mygpo.api.httpresponse import JsonResponse @@ -26,6 +26,7 @@ from django.views.decorators.csrf import csrf_exempt from django.shortcuts import get_object_or_404 from mygpo.search.models import SearchEntry from django.utils.translation import ugettext as _ +from mygpo.decorators import allowed_methods try: @@ -54,6 +55,7 @@ def check_format(fn): @require_valid_user @check_username @check_format +@allowed_methods(['GET', 'PUT', 'POST']) def subscriptions(request, username, device_uid, format): if request.method == 'GET': @@ -65,18 +67,13 @@ def subscriptions(request, username, device_uid, format): subscriptions = parse_subscription(request.raw_post_data, format) return set_subscriptions(subscriptions, request.user, device_uid) - else: - return HttpResponseNotAllowed(['GET', 'PUT', 'POST']) - @csrf_exempt @require_valid_user @check_username @check_format +@allowed_methods(['GET']) def all_subscriptions(request, username, format): - if request.method != 'GET': - return HttpResponseNotAllowed(['GET']) - subscriptions = get_all_subscriptions(request.user) title = _('%(username)s\'s Subscription List') % {'username': username} return format_podcast_list(subscriptions, format, title) @@ -170,10 +167,8 @@ def set_subscriptions(urls, user, device_uid): @check_format +@allowed_methods(['GET']) def toplist(request, count, format): - if request.method != 'GET': - return HttpResponseNotAllowed(['GET']) - if int(count) not in range(1,100): count = 100 @@ -192,10 +187,8 @@ def toplist(request, count, format): @check_format +@allowed_methods(['GET']) def search(request, format): - if request.method != 'GET': - return HttpResponseNotAllowed(['GET']) - query = request.GET.get('q', '').encode('utf-8') if not query: @@ -210,10 +203,8 @@ def search(request, format): @require_valid_user @check_format +@allowed_methods(['GET']) def suggestions(request, count, format): - if request.method != 'GET': - return HttpResponseNotAllowed(['GET']) - if int(count) not in range(1,100): count = 100 diff --git a/mygpo/decorators.py b/mygpo/decorators.py index 63139cab..d981880b 100644 --- a/mygpo/decorators.py +++ b/mygpo/decorators.py @@ -21,7 +21,7 @@ from django.shortcuts import render_to_response from django.template import RequestContext from mygpo.web.models import SecurityToken from django.contrib.auth.models import User -from django.http import Http404, HttpResponseForbidden +from django.http import Http404, HttpResponseForbidden, HttpResponseNotAllowed import random import string import gc @@ -78,3 +78,16 @@ def manual_gc(view): return tmp + +def allowed_methods(methods): + def decorator(fn): + def tmp(request, *args, **kwargs): + if request.method in methods: + return fn(request, *args, **kwargs) + else: + return HttpResponseNotAllowed(methods) + + return tmp + + return decorator + diff --git a/mygpo/publisher/views.py b/mygpo/publisher/views.py index d9fe0e1f..3b43fae1 100644 --- a/mygpo/publisher/views.py +++ b/mygpo/publisher/views.py @@ -9,7 +9,7 @@ from mygpo.publisher.forms import SearchPodcastForm, EpisodeForm, PodcastForm from mygpo.publisher.utils import listener_data, episode_listener_data, check_publisher_permission, episode_list, subscriber_data, device_stats, episode_heatmap from django.contrib.sites.models import Site from mygpo.data.feeddownloader import update_podcasts -from mygpo.decorators import requires_token +from mygpo.decorators import requires_token, allowed_methods from mygpo.web.models import SecurityToken from django.contrib.auth.models import User @@ -43,6 +43,7 @@ def search_podcast(request): return HttpResponseRedirect('/publisher/') @require_publisher +@allowed_methods(['GET', 'POST']) def podcast(request, id): p = get_object_or_404(Podcast, pk=id) @@ -141,6 +142,7 @@ def episodes(request, id): @require_publisher +@allowed_methods(['GET', 'POST']) def episode(request, id): e = get_object_or_404(Episode, pk=id) diff --git a/mygpo/web/views/device.py b/mygpo/web/views/device.py index 9274651e..774e59d5 100644 --- a/mygpo/web/views/device.py +++ b/mygpo/web/views/device.py @@ -16,7 +16,7 @@ # from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, Http404, HttpResponseForbidden +from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, Http404, HttpResponseForbidden from django.contrib.auth.models import User from django.template import RequestContext from mygpo.api.models import Podcast, Episode, Device, EpisodeAction, SubscriptionAction, ToplistEntry, EpisodeToplistEntry, Subscription, SuggestionEntry, SyncGroup, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION, SubscriptionMeta @@ -33,7 +33,7 @@ from mygpo.api.sanitizing import sanitize_url from mygpo.log import log from mygpo.utils import daterange from mygpo.api import simple -from mygpo.decorators import manual_gc +from mygpo.decorators import manual_gc, allowed_methods import re import random import string @@ -76,6 +76,7 @@ def show(request, device_id, error_message=None): @login_required +@allowed_methods(['GET', 'POST']) def edit(request, device_id): device = get_object_or_404(Device, id=device_id, user=request.user) @@ -125,10 +126,8 @@ def opml(request, device_id): @manual_gc @login_required +@allowed_methods(['POST']) def delete(request, device_id): - if request.method != 'POST': - return HttpResponseNotAllowed(['POST']) - device = Device.objects.get(pk=device_id) device.deleted = True device.save() @@ -161,11 +160,8 @@ def undelete(request, device_id): @manual_gc @login_required +@allowed_methods(['POST']) def sync(request, device_id): - - if request.method != 'POST': - return HttpResponseNotAllowed(['POST']) - form = SyncForm(request.POST) if not form.is_valid(): return HttpResponseBadRequest('invalid') @@ -184,10 +180,8 @@ def sync(request, device_id): @manual_gc @login_required +@allowed_methods(['GET']) def unsync(request, device_id): - if request.method != 'GET': - return HttpResponseNotAllowed(['GET']) - dev = Device.objects.get(pk=device_id) try: diff --git a/mygpo/web/views/episode.py b/mygpo/web/views/episode.py index 86d40ada..4e5aa335 100644 --- a/mygpo/web/views/episode.py +++ b/mygpo/web/views/episode.py @@ -16,7 +16,7 @@ # from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, Http404, HttpResponseForbidden +from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, Http404, HttpResponseForbidden from django.template import RequestContext from mygpo.api.models import Podcast, Episode, Device, EpisodeAction, Subscription from mygpo.api.models.episodes import Chapter diff --git a/mygpo/web/views/podcast.py b/mygpo/web/views/podcast.py index 3f491c75..d310fb5a 100644 --- a/mygpo/web/views/podcast.py +++ b/mygpo/web/views/podcast.py @@ -11,13 +11,14 @@ from django.utils.translation import ugettext as _ from mygpo.api.models import Podcast, Episode, EpisodeAction, Device, SubscriptionAction, Subscription, SUBSCRIBE_ACTION, UNSUBSCRIBE_ACTION, SyncGroup from mygpo.web.forms import PrivacyForm, SyncForm from mygpo.data.models import Listener, PodcastTag -from mygpo.decorators import manual_gc +from mygpo.decorators import manual_gc, allowed_methods from mygpo.utils import daterange MAX_TAGS_ON_PAGE=50 +@allowed_methods(['GET', 'POST']) def show(request, pid): podcast = get_object_or_404(Podcast, pk=pid) episodes = episode_list(podcast, request.user) @@ -184,6 +185,7 @@ def remove_tag(request, pid): @manual_gc @login_required +@allowed_methods(['GET', 'POST']) def subscribe(request, pid): podcast = get_object_or_404(Podcast, pk=pid) error_message = None diff --git a/mygpo/web/views/public.py b/mygpo/web/views/public.py index 08e7d3ac..ab31a078 100644 --- a/mygpo/web/views/public.py +++ b/mygpo/web/views/public.py @@ -16,7 +16,7 @@ # from django.shortcuts import render_to_response -from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, HttpResponseNotAllowed, Http404, HttpResponseForbidden +from django.http import HttpResponseRedirect, HttpResponse, HttpResponseBadRequest, Http404, HttpResponseForbidden from django.template import RequestContext from mygpo.api.models import Podcast, Episode, Subscription from mygpo.api import backend diff --git a/mygpo/web/views/settings.py b/mygpo/web/views/settings.py index 454c672d..3fe85330 100644 --- a/mygpo/web/views/settings.py +++ b/mygpo/web/views/settings.py @@ -25,7 +25,7 @@ from mygpo.web.forms import UserAccountForm from django.forms import ValidationError from django.utils.translation import ugettext as _ from mygpo.api.basic_auth import require_valid_user -from mygpo.decorators import manual_gc +from mygpo.decorators import manual_gc, allowed_methods from django.contrib.auth.decorators import login_required from django.shortcuts import get_object_or_404 from django.contrib.sites.models import Site @@ -33,6 +33,7 @@ from django.contrib.sites.models import Site @manual_gc @login_required +@allowed_methods(['GET', 'POST']) def account(request): success = False error_message = '' @@ -83,6 +84,7 @@ def account(request): @manual_gc @login_required +@allowed_methods(['GET', 'POST']) def delete_account(request): if request.method == 'GET': @@ -102,14 +104,9 @@ def delete_account(request): @manual_gc @login_required +@allowed_methods(['GET']) def privacy(request): - if request.method == 'GET': - form = UserAccountForm({ - 'email': request.user.email, - 'public': request.user.get_profile().public_profile - }) - if 'private_subscriptions' in request.GET: request.user.get_profile().settings['public_profile'] = False request.user.get_profile().save() diff --git a/mygpo/web/views/users.py b/mygpo/web/views/users.py index e7a40a10..1ef577be 100644 --- a/mygpo/web/views/users.py +++ b/mygpo/web/views/users.py @@ -27,7 +27,7 @@ from mygpo.api.models import UserProfile from mygpo.web.forms import RestorePasswordForm from django.contrib.sites.models import Site from django.conf import settings -from mygpo.decorators import requires_token, manual_gc +from mygpo.decorators import requires_token, manual_gc, allowed_methods from django.utils.translation import ugettext as _ import string import random @@ -135,11 +135,9 @@ def get_user(username, email): else: raise User.DoesNotExist('neither username nor email provided') -def restore_password(request): - - if request.method != 'POST': - return HttpResponseRedirect('/login/') +@allowed_methods(['POST']) +def restore_password(request): form = RestorePasswordForm(request.POST) if not form.is_valid(): return HttpResponseRedirect('/login/') @@ -164,6 +162,7 @@ def restore_password(request): @manual_gc +@allowed_methods(['GET', 'POST']) def resend_activation(request): error_message = ''