From 751e66032f228c28c90118f874d84ca59ddfe5b3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20K=C3=B6gl?= Date: Sun, 29 Sep 2013 19:50:41 +0200 Subject: [PATCH] Access-Control-Allow-Origin: * in all API requests --- mygpo/api/advanced/__init__.py | 7 ++++++- mygpo/api/advanced/auth.py | 4 +++- mygpo/api/advanced/directory.py | 5 +++++ mygpo/api/advanced/episode.py | 3 ++- mygpo/api/advanced/lists.py | 8 +++++++- mygpo/api/advanced/settings.py | 3 ++- mygpo/api/advanced/sync.py | 3 ++- mygpo/api/advanced/updates.py | 2 ++ mygpo/api/simple.py | 8 +++++++- mygpo/decorators.py | 14 ++++++++++++++ 10 files changed, 50 insertions(+), 7 deletions(-) diff --git a/mygpo/api/advanced/__init__.py b/mygpo/api/advanced/__init__.py index 4e668e78..bbfef0ff 100644 --- a/mygpo/api/advanced/__init__.py +++ b/mygpo/api/advanced/__init__.py @@ -35,7 +35,7 @@ from mygpo.api.advanced.directory import episode_data from mygpo.api.backend import get_device, BulkSubscribe from mygpo.utils import format_time, parse_bool, get_timestamp, \ parse_request_body, normalize_feed_url -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin from mygpo.core.tasks import auto_flattr_episode from mygpo.users.models import EpisodeAction, \ DeviceDoesNotExist, DeviceUIDException, \ @@ -67,6 +67,7 @@ EPISODE_ACTION_KEYS = ('position', 'episode', 'action', 'device', 'timestamp', @check_username @never_cache @allowed_methods(['GET', 'POST']) +@cors_origin() def subscriptions(request, username, device_uid): now = datetime.now() @@ -177,6 +178,7 @@ def get_subscription_changes(user, device, since, until): @check_username @never_cache @allowed_methods(['GET', 'POST']) +@cors_origin() def episodes(request, username, version=1): version = int(version) @@ -437,6 +439,7 @@ def parse_episode_action(action, user, update_urls, now, ua_string): # Workaround for mygpoclient 1.0: It uses "PUT" requests # instead of "POST" requests for uploading device settings @allowed_methods(['POST', 'PUT']) +@cors_origin() def device(request, username, device_uid): d = get_device(request.user, device_uid, request.META.get('HTTP_USER_AGENT', '')) @@ -484,6 +487,7 @@ def valid_episodeaction(type): @check_username @never_cache @allowed_methods(['GET']) +@cors_origin() def devices(request, username): devices = filter(lambda d: not d.deleted, request.user.devices) devices = map(device_data, devices) @@ -502,6 +506,7 @@ def device_data(device): @require_valid_user @check_username @never_cache +@cors_origin() def favorites(request, username): favorites = favorite_episodes_for_user(request.user) domain = RequestSite(request).domain diff --git a/mygpo/api/advanced/auth.py b/mygpo/api/advanced/auth.py index f3ffe42d..e4a2b725 100644 --- a/mygpo/api/advanced/auth.py +++ b/mygpo/api/advanced/auth.py @@ -23,7 +23,7 @@ from django.views.decorators.csrf import csrf_exempt from django.views.decorators.cache import never_cache from mygpo.api.basic_auth import require_valid_user, check_username -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin @csrf_exempt @@ -31,6 +31,7 @@ from mygpo.decorators import allowed_methods @check_username @allowed_methods(['POST']) @never_cache +@cors_origin() def login(request, username): """ authenticates the user with regular http basic auth @@ -44,6 +45,7 @@ def login(request, username): @check_username @allowed_methods(['POST']) @never_cache +@cors_origin() def logout(request, username): """ logs out the user. does nothing if he wasn't logged in diff --git a/mygpo/api/advanced/directory.py b/mygpo/api/advanced/directory.py index c2fd2c01..eee4d2b2 100644 --- a/mygpo/api/advanced/directory.py +++ b/mygpo/api/advanced/directory.py @@ -26,6 +26,7 @@ from mygpo.core.models import Podcast, PodcastGroup from mygpo.utils import parse_range, normalize_feed_url from mygpo.directory.tags import Topics from mygpo.web.utils import get_episode_link_target, get_podcast_link_target +from mygpo.decorators import cors_origin from mygpo.api.httpresponse import JsonResponse from mygpo.db.couchdb.episode import episode_for_podcast_url from mygpo.db.couchdb.podcast import podcast_by_id, podcast_for_url @@ -34,6 +35,7 @@ from mygpo.db.couchdb.directory import category_for_tag @csrf_exempt @cache_page(60 * 60 * 24) +@cors_origin() def top_tags(request, count): count = parse_range(count, 1, 100, 100) tag_cloud = Topics(count, num_cat=0) @@ -43,6 +45,7 @@ def top_tags(request, count): @csrf_exempt @cache_page(60 * 60 * 24) +@cors_origin() def tag_podcasts(request, tag, count): count = parse_range(count, 1, 100, 100) category = category_for_tag(tag) @@ -56,6 +59,7 @@ def tag_podcasts(request, tag, count): @cache_page(60 * 60) +@cors_origin() def podcast_info(request): url = normalize_feed_url(request.GET.get('url', '')) @@ -74,6 +78,7 @@ def podcast_info(request): @cache_page(60 * 60) +@cors_origin() def episode_info(request): podcast_url = normalize_feed_url(request.GET.get('podcast', '')) episode_url = normalize_feed_url(request.GET.get('url', '')) diff --git a/mygpo/api/advanced/episode.py b/mygpo/api/advanced/episode.py index 6c54afbb..87d1ddb9 100644 --- a/mygpo/api/advanced/episode.py +++ b/mygpo/api/advanced/episode.py @@ -30,7 +30,7 @@ from mygpo.api.exceptions import ParameterMissing from mygpo.api.backend import get_device from mygpo.users.models import Chapter from mygpo.utils import parse_time, parse_request_body, normalize_feed_url -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin from mygpo.api.basic_auth import require_valid_user, check_username from mygpo.db.couchdb.episode import episode_for_podcast_url from mygpo.db.couchdb.episode_state import episode_state_for_user_episode, \ @@ -42,6 +42,7 @@ from mygpo.db.couchdb.episode_state import episode_state_for_user_episode, \ @check_username @never_cache @allowed_methods(['POST', 'GET']) +@cors_origin() def chapters(request, username): now = datetime.utcnow() diff --git a/mygpo/api/advanced/lists.py b/mygpo/api/advanced/lists.py index 5a3c6e99..13b9198b 100644 --- a/mygpo/api/advanced/lists.py +++ b/mygpo/api/advanced/lists.py @@ -33,7 +33,7 @@ from mygpo.api.httpresponse import JsonResponse from mygpo.share.models import PodcastList from mygpo.api.basic_auth import require_valid_user, check_username from mygpo.core.models import Podcast -from mygpo.decorators import allowed_methods, repeat_on_conflict +from mygpo.decorators import allowed_methods, repeat_on_conflict, cors_origin from mygpo.api.simple import parse_subscription, format_podcast_list, \ check_format from mygpo.share.views import list_decorator @@ -50,6 +50,7 @@ from mygpo.db.couchdb.podcastlist import podcastlist_for_user_slug, \ @check_format @never_cache @allowed_methods(['POST']) +@cors_origin() def create(request, username, format): """ Creates a new podcast list and links to it in the Location header """ @@ -100,6 +101,7 @@ def _get_list_data(l, username, domain): @csrf_exempt @never_cache @allowed_methods(['GET']) +@cors_origin() def get_lists(request, username): """ Returns a list of all podcast lists by the given user """ @@ -122,6 +124,7 @@ def get_lists(request, username): @check_format @never_cache @allowed_methods(['GET', 'PUT', 'DELETE']) +@cors_origin() def podcast_list(request, *args, **kwargs): handlers = dict( @@ -135,6 +138,7 @@ def podcast_list(request, *args, **kwargs): @never_cache @list_decorator(must_own=False) +@cors_origin() def get_list(request, plist, owner, format): """ Returns the contents of the podcast list """ @@ -158,6 +162,7 @@ def get_list(request, plist, owner, format): @never_cache @require_valid_user @list_decorator(must_own=True) +@cors_origin() def update_list(request, plist, owner, format): """ Replaces the podcasts in the list and returns 204 No Content """ @@ -183,6 +188,7 @@ def update_list(request, plist, owner, format): @never_cache @require_valid_user @list_decorator(must_own=True) +@cors_origin() def delete_list(request, plist, owner, format): """ Delete the podcast list and returns 204 No Content """ diff --git a/mygpo/api/advanced/settings.py b/mygpo/api/advanced/settings.py index 66d6050e..8b7a4650 100644 --- a/mygpo/api/advanced/settings.py +++ b/mygpo/api/advanced/settings.py @@ -19,7 +19,7 @@ from django.http import HttpResponseBadRequest, Http404, HttpResponseNotFound from django.views.decorators.csrf import csrf_exempt from django.views.decorators.cache import never_cache -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin from mygpo.core.models import Podcast from mygpo.utils import parse_request_body from mygpo.api.basic_auth import require_valid_user, check_username @@ -36,6 +36,7 @@ from mygpo.db.couchdb.episode_state import episode_state_for_user_episode @check_username @never_cache @allowed_methods(['GET', 'POST']) +@cors_origin() def main(request, username, scope): db = get_main_database() diff --git a/mygpo/api/advanced/sync.py b/mygpo/api/advanced/sync.py index 82cad039..9a94ac4d 100644 --- a/mygpo/api/advanced/sync.py +++ b/mygpo/api/advanced/sync.py @@ -19,7 +19,7 @@ from django.http import HttpResponseBadRequest, HttpResponseNotFound from django.views.decorators.csrf import csrf_exempt from django.views.decorators.cache import never_cache -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin from mygpo.core.json import JSONDecodeError from mygpo.utils import parse_request_body from mygpo.api.basic_auth import require_valid_user, check_username @@ -33,6 +33,7 @@ from mygpo.users.tasks import sync_user @check_username @never_cache @allowed_methods(['GET', 'POST']) +@cors_origin() def main(request, username): """ API Endpoint for Device Synchronisation """ diff --git a/mygpo/api/advanced/updates.py b/mygpo/api/advanced/updates.py index adaa5ac9..795c3077 100644 --- a/mygpo/api/advanced/updates.py +++ b/mygpo/api/advanced/updates.py @@ -37,6 +37,7 @@ from mygpo.utils import parse_bool, get_timestamp from mygpo.users.models import DeviceDoesNotExist from mygpo.users.subscriptions import subscription_changes, podcasts_for_states from mygpo.api.basic_auth import require_valid_user, check_username +from mygpo.decorators import cors_origin from mygpo.db.couchdb.episode import episodes_for_podcast from mygpo.db.couchdb.episode_state import get_podcasts_episode_states from mygpo.db.couchdb.podcast_state import podcast_states_for_device @@ -57,6 +58,7 @@ class DeviceUpdates(View): @method_decorator(require_valid_user) @method_decorator(check_username) @method_decorator(never_cache) + @method_decorator(cors_origin) def get(self, request, username, device_uid): now = datetime.now() diff --git a/mygpo/api/simple.py b/mygpo/api/simple.py index 3712f294..f7c56e5f 100644 --- a/mygpo/api/simple.py +++ b/mygpo/api/simple.py @@ -41,7 +41,7 @@ from mygpo.directory.toplist import PodcastToplist from mygpo.directory.models import ExamplePodcasts from mygpo.api.advanced.directory import podcast_data from mygpo.directory.search import search_podcasts -from mygpo.decorators import allowed_methods +from mygpo.decorators import allowed_methods, cors_origin from mygpo.utils import parse_range, normalize_feed_url from mygpo.core.json import json, JSONDecodeError from mygpo.db.couchdb import BulkException @@ -70,6 +70,7 @@ def check_format(fn): @check_format @never_cache @allowed_methods(['GET', 'PUT', 'POST']) +@cors_origin() def subscriptions(request, username, device_uid, format): user_agent = request.META.get('HTTP_USER_AGENT', '') @@ -96,6 +97,7 @@ def subscriptions(request, username, device_uid, format): @check_format @never_cache @allowed_methods(['GET']) +@cors_origin() def all_subscriptions(request, username, format): try: @@ -240,6 +242,7 @@ def set_subscriptions(urls, user, device_uid, user_agent): @check_format @allowed_methods(['GET']) @cache_page(60 * 60) +@cors_origin() def toplist(request, count, format): count = parse_range(count, 1, 100, 100) @@ -287,6 +290,7 @@ def toplist(request, count, format): @check_format @cache_page(60 * 60) @allowed_methods(['GET']) +@cors_origin() def search(request, format): NUM_RESULTS = 20 @@ -316,6 +320,7 @@ def search(request, format): @check_format @never_cache @allowed_methods(['GET']) +@cors_origin() def suggestions(request, count, format): count = parse_range(count, 1, 100, 100) @@ -330,6 +335,7 @@ def suggestions(request, count, format): @check_format @allowed_methods(['GET']) @cache_page(60 * 60) +@cors_origin() def example_podcasts(request, format): podcasts = cache.get('example-podcasts', None) diff --git a/mygpo/decorators.py b/mygpo/decorators.py index 4dbe5467..3ff1de79 100644 --- a/mygpo/decorators.py +++ b/mygpo/decorators.py @@ -164,3 +164,17 @@ def query_if_required(): return wrapper return decorator + + +def cors_origin(allowed_origin='*'): + """ Adds an Access-Control-Allow-Origin header to the response """ + + def decorator(f): + @wraps(f) + def wrapper(*args, **kwargs): + resp = f(*args, **kwargs) + resp['Access-Control-Allow-Origin'] = allowed_origin + return resp + + return wrapper + return decorator -- 2.11.4.GIT