From 9e830d1df8de2cf22fd78e47601e584465d268f5 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Chibon Date: Apr 19 2018 10:07:18 +0000 Subject: Insert CORS headers if some are configured Fixes https://pagure.io/waiverdb/issue/160 Signed-off-by: Pierre-Yves Chibon Signed-off-by: Pierre-Yves Chibon --- diff --git a/tests/conftest.py b/tests/conftest.py index b058202..69753f9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -70,3 +70,8 @@ def enable_kerberos(app, monkeypatch): @pytest.fixture() def enable_ssl(app, monkeypatch): monkeypatch.setitem(app.config, 'AUTH_METHOD', 'SSL') + + +@pytest.fixture() +def enable_cors(app, monkeypatch): + monkeypatch.setitem(app.config, 'CORS_URL', 'https://bodhi.fedoraproject.org') diff --git a/tests/test_api_v10.py b/tests/test_api_v10.py index 8908db9..21dbdcf 100644 --- a/tests/test_api_v10.py +++ b/tests/test_api_v10.py @@ -1,10 +1,13 @@ # SPDX-License-Identifier: GPL-2.0+ -import json -from .utils import create_waiver import datetime +import json + +import pytest from requests import ConnectionError, HTTPError from mock import patch, Mock + +from .utils import create_waiver from waiverdb import __version__ @@ -464,3 +467,67 @@ def test_about_endpoint(client): assert r.status_code == 200 assert output['version'] == __version__ assert output['auth_method'] == client.application.config['AUTH_METHOD'] + + +@pytest.mark.usefixtures('enable_cors') +def test_cors_about(client, session): + r = client.get('/api/v1.0/about') + + assert 'Access-Control-Allow-Origin' in list(r.headers.keys()) + assert 'Access-Control-Allow-Headers' in list(r.headers.keys()) + assert 'Access-Control-Allow-Method' in list(r.headers.keys()) + assert r.headers['Access-Control-Allow-Origin'] == 'https://bodhi.fedoraproject.org' + assert r.headers['Access-Control-Allow-Headers'] == 'Content-Type' + assert r.headers['Access-Control-Allow-Method'] == 'POST, OPTIONS' + + output = json.loads(r.get_data(as_text=True)) + assert r.status_code == 200 + assert output['version'] == __version__ + + +def test_no_cors_about(client, session): + r = client.get('/api/v1.0/about') + + assert 'Access-Control-Allow-Origin' not in list(r.headers.keys()) + assert 'Access-Control-Allow-Headers' not in list(r.headers.keys()) + assert 'Access-Control-Allow-Method' not in list(r.headers.keys()) + + output = json.loads(r.get_data(as_text=True)) + assert r.status_code == 200 + assert output['version'] == __version__ + + +@pytest.mark.usefixtures('enable_cors') +def test_cors_waivers(client, session): + for i in range(0, 3): + create_waiver(session, subject={"subject%d" % i: "%d" % i}, + testcase="case %d" % i, username='foo %d' % i, + product_version='foo-%d' % i, comment='bla bla bla') + r = client.get('/api/v1.0/waivers/') + + assert 'Access-Control-Allow-Origin' in list(r.headers.keys()) + assert 'Access-Control-Allow-Headers' in list(r.headers.keys()) + assert 'Access-Control-Allow-Method' in list(r.headers.keys()) + assert r.headers['Access-Control-Allow-Origin'] == 'https://bodhi.fedoraproject.org' + assert r.headers['Access-Control-Allow-Headers'] == 'Content-Type' + assert r.headers['Access-Control-Allow-Method'] == 'POST, OPTIONS' + + res_data = json.loads(r.get_data(as_text=True)) + assert r.status_code == 200 + assert len(res_data['data']) == 3 + + +def test_no_cors_waivers(client, session): + for i in range(0, 3): + create_waiver(session, subject={"subject%d" % i: "%d" % i}, + testcase="case %d" % i, username='foo %d' % i, + product_version='foo-%d' % i, comment='bla bla bla') + r = client.get('/api/v1.0/waivers/') + + assert 'Access-Control-Allow-Origin' not in list(r.headers.keys()) + assert 'Access-Control-Allow-Headers' not in list(r.headers.keys()) + assert 'Access-Control-Allow-Method' not in list(r.headers.keys()) + + res_data = json.loads(r.get_data(as_text=True)) + assert r.status_code == 200 + assert len(res_data['data']) == 3 diff --git a/waiverdb/api_v1.py b/waiverdb/api_v1.py index ffe7a9b..10d6bd1 100644 --- a/waiverdb/api_v1.py +++ b/waiverdb/api_v1.py @@ -10,7 +10,7 @@ from sqlalchemy.sql.expression import func, cast from waiverdb import __version__ from waiverdb.models import db, Waiver -from waiverdb.utils import reqparse_since, json_collection, jsonp +from waiverdb.utils import reqparse_since, json_collection, jsonp, insert_headers from waiverdb.fields import waiver_fields import waiverdb.auth @@ -147,7 +147,8 @@ class WaiversResource(Resource): Waiver.testcase) query = query.filter(Waiver.id.in_(subquery)) query = query.order_by(Waiver.timestamp.desc()) - return json_collection(query, args['page'], args['limit']) + return insert_headers( + json_collection(query, args['page'], args['limit'])) @jsonp @marshal_with(waiver_fields) @@ -271,7 +272,7 @@ class WaiverResource(Resource): :statuscode 404: No waiver exists with that ID. """ try: - return Waiver.query.get_or_404(waiver_id) + return insert_headers(Waiver.query.get_or_404(waiver_id)) except Exception as NotFound: raise type(NotFound)('Waiver not found') @@ -401,7 +402,7 @@ class GetWaiversBySubjectsAndTestcases(Resource): query = query.filter(Waiver.id.in_(subquery)) query = query.order_by(Waiver.timestamp.desc()) - return {'data': marshal(query.all(), waiver_fields)} + return insert_headers({'data': marshal(query.all(), waiver_fields)}) class AboutResource(Resource): @@ -428,7 +429,8 @@ class AboutResource(Resource): :statuscode 200: Currently running waiverdb software version and authentication are returned. """ - return {'version': __version__, 'auth_method': current_app.config['AUTH_METHOD']} + return insert_headers( + {'version': __version__, 'auth_method': current_app.config['AUTH_METHOD']}) # set up the Api resource routing here diff --git a/waiverdb/utils.py b/waiverdb/utils.py index 30e0c02..fbd5e8c 100644 --- a/waiverdb/utils.py +++ b/waiverdb/utils.py @@ -123,6 +123,8 @@ def insert_headers(response): """ Insert the CORS headers for the give reponse if there are any configured for the application. """ + if isinstance(response, dict): + response = jsonify(response) if current_app.config.get('CORS_URL'): response.headers['Access-Control-Allow-Origin'] = \ current_app.config['CORS_URL']