From 07229fdec88bce101835c3714359ec9596cf1a66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= Date: Tue, 28 Jul 2015 11:21:57 +0200 Subject: [PATCH] api: allow unknown NameID on categories and formdefs API endpoints (#7957) --- tests/test_api.py | 27 +++++++++++++++++++++++++++ wcs/api.py | 5 +++-- wcs/forms/root.py | 21 +++++++++++++++++---- wcs/qommon/errors.py | 4 ++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/tests/test_api.py b/tests/test_api.py index 6707c20..f16b6ca 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -111,6 +111,17 @@ def test_get_user_from_api_query_string_error_missing_email(): output = get_app(pub).get('/user?%s&signature=%s' % (query, signature), status=403) assert output.json['err_desc'] == 'no user specified' +def test_get_user_from_api_query_string_error_unknown_nameid(): + timestamp = datetime.datetime.utcnow().isoformat()[:19] + 'Z' + query = 'format=json&orig=coucou&algo=sha1&NameID=xxx×tamp=' + timestamp + signature = urllib.quote( + base64.b64encode( + hmac.new('1234', + query, + hashlib.sha1).digest())) + output = get_app(pub).get('/user?%s&signature=%s' % (query, signature), status=403) + assert output.json['err_desc'] == 'unknown NameID' + def test_get_user_from_api_query_string_error_missing_email_valid_endpoint(): # check it's ok to sign an URL without specifiying an user if the endpoint # works fine without user. @@ -123,6 +134,22 @@ def test_get_user_from_api_query_string_error_missing_email_valid_endpoint(): hashlib.sha1).digest())) output = get_app(pub).get('/categories?%s&signature=%s' % (query, signature)) assert output.json == {'data': []} + output = get_app(pub).get('/json?%s&signature=%s' % (query, signature)) + assert output.json == [] + +def test_get_user_from_api_query_string_error_unknown_nameid_valid_endpoint(): + # check the categories and forms endpoints accept an unknown NameID + timestamp = datetime.datetime.utcnow().isoformat()[:19] + 'Z' + query = 'format=json&NameID=xxx&orig=coucou&algo=sha1×tamp=' + timestamp + signature = urllib.quote( + base64.b64encode( + hmac.new('1234', + query, + hashlib.sha1).digest())) + output = get_app(pub).get('/categories?%s&signature=%s' % (query, signature)) + assert output.json == {'data': []} + output = get_app(pub).get('/json?%s&signature=%s' % (query, signature)) + assert output.json == [] def test_get_user_from_api_query_string_error_success_sha1(local_user): timestamp = datetime.datetime.utcnow().isoformat()[:19] + 'Z' diff --git a/wcs/api.py b/wcs/api.py index a400ae7..1a9089a 100644 --- a/wcs/api.py +++ b/wcs/api.py @@ -26,7 +26,8 @@ import random from quixote import get_request, get_publisher, get_response from quixote.directory import Directory -from qommon.errors import AccessForbiddenError, QueryError, TraversalError +from qommon.errors import (AccessForbiddenError, QueryError, TraversalError, + UnknownNameIdAccessForbiddenError) from wcs.formdef import FormDef from wcs.roles import Role @@ -92,7 +93,7 @@ def get_user_from_api_query_string(): if users: user = users[0] else: - raise AccessForbiddenError('unknown NameID') + raise UnknownNameIdAccessForbiddenError('unknown NameID') return user diff --git a/wcs/forms/root.py b/wcs/forms/root.py index 285dfad..c98a251 100644 --- a/wcs/forms/root.py +++ b/wcs/forms/root.py @@ -1202,8 +1202,16 @@ class RootDirectory(AccessControlled, Directory): return r.getvalue() def json(self): - from wcs.api import is_url_signed, get_user_from_api_query_string - user = get_user_from_api_query_string() or get_request().user + from wcs.api import (is_url_signed, get_user_from_api_query_string, + UnknownNameIdAccessForbiddenError) + try: + user = get_user_from_api_query_string() or get_request().user + except UnknownNameIdAccessForbiddenError: + # if authenticating the user via the query string failed, return + # results for the anonymous case; user is set to 'False' as a + # signed URL with a None user is considered like an appropriate + # webservice call. + user = False list_all_forms = (user and user.is_admin) or (is_url_signed() and user is None) list_forms = [] @@ -1292,8 +1300,13 @@ class RootDirectory(AccessControlled, Directory): return r.getvalue() def categories_json(self): - from wcs.api import get_user_from_api_query_string - user = get_user_from_api_query_string() or get_request().user + from wcs.api import get_user_from_api_query_string, UnknownNameIdAccessForbiddenError + try: + user = get_user_from_api_query_string() or get_request().user + except UnknownNameIdAccessForbiddenError: + # the name id was unknown, return the categories for anonymous + # users. + user = None list_categories = [] charset = get_publisher().site_charset categories = self.get_categories(user) diff --git a/wcs/qommon/errors.py b/wcs/qommon/errors.py index b64bb1f..4bd0011 100644 --- a/wcs/qommon/errors.py +++ b/wcs/qommon/errors.py @@ -39,6 +39,10 @@ class AccessForbiddenError(AccessError): location_hint = self.location_hint) +class UnknownNameIdAccessForbiddenError(AccessForbiddenError): + pass + + class AccessUnauthorizedError(AccessForbiddenError): def render(self): session = quixote.get_session() -- 2.5.0