api: fix handling of query string and errors in provision API (#57361)

This commit is contained in:
Frédéric Péters 2021-09-28 20:15:29 +02:00
parent 89a82fe043
commit 33125abda7
3 changed files with 63 additions and 5 deletions

View File

@ -1,13 +1,16 @@
import os
import uuid
import pytest
from wcs.api_utils import sign_url
from wcs.ctl.hobo_notify import CmdHoboNotify
from wcs.qommon import force_str
from wcs.qommon import storage as st
from wcs.qommon.afterjobs import AfterJob
from wcs.qommon.http_request import HTTPRequest
from .utilities import create_temporary_pub
from .utilities import create_temporary_pub, get_app
def pytest_generate_tests(metafunc):
@ -24,6 +27,14 @@ def pub(request):
pub.cfg['sp'] = {'saml2_providerid': 'test'}
pub.write_cfg()
with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
fd.write(
'''\
[api-secrets]
coucou = 1234
'''
)
pub.role_class.wipe()
r = pub.role_class(name='Service étt civil')
r.slug = 'service-ett-civil'
@ -849,3 +860,42 @@ def test_process_user_deprovision_with_data(pub):
CmdHoboNotify.process_notification(notification)
assert User.count() == 1
assert len(User.select([st.NotNull('deleted_timestamp')])) == 1
def test_provision_http_endpoint(pub):
get_app(pub).get('/__provision__/', status=403)
get_app(pub).get(sign_url('/__provision__/?orig=coucou', '1234'), status=400)
notification = {
'@type': 'provision',
'issuer': 'http://idp.example.net/idp/saml/metadata',
'audience': ['test'],
'objects': {
'@type': 'user',
'data': [
{
'uuid': 'a' * 32,
'first_name': 'John',
'last_name': 'Doé',
'email': 'john.doe@example.net',
'zipcode': '13400',
'is_superuser': False,
'is_active': True,
'roles': [],
}
],
},
}
AfterJob.wipe()
pub.user_class.wipe()
get_app(pub).post_json(sign_url('/__provision__/?orig=coucou', '1234'), notification)
assert AfterJob.count() == 1 # async by default
assert pub.user_class.count() == 1
AfterJob.wipe()
pub.user_class.wipe()
get_app(pub).post_json(sign_url('/__provision__/?orig=coucou&sync=1', '1234'), notification)
assert AfterJob.count() == 0 # sync
assert pub.user_class.count() == 1

View File

@ -1345,7 +1345,7 @@ def provisionning(request):
if not is_url_signed():
raise AccessForbiddenError()
sync = request.form.get('sync') == '1'
sync = request.GET.get('sync') == '1'
if sync:
CmdHoboNotify().process_notification(get_request().json)

View File

@ -263,12 +263,20 @@ class PublishErrorMiddleware(MiddlewareMixin):
if not isinstance(exception, PublishError):
return None
request = get_request()
exception_body = exception.render()
content_type = None
status_code = getattr(exception, 'status_code', None)
if hasattr(exception, 'render'):
exception_body = exception.render()
else:
exception_body = str(exception)
content_type = 'text/plain'
django_response = HttpResponse(
exception_body,
content_type=request.response.content_type,
status=request.response.status_code,
content_type=content_type or request.response.content_type,
status=status_code or request.response.status_code,
reason=request.response.reason_phrase,
)