wcs: add access control (#49406)

This commit is contained in:
Lauréline Guérin 2020-12-15 15:18:39 +01:00
parent 3b1b0d3ca1
commit d1f886b46d
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
3 changed files with 102 additions and 4 deletions

View File

@ -32,12 +32,25 @@ def get_default_wcs_service_key():
class LazyCardDefObjectsManager(object):
def __init__(self, service_key, card_id):
def __init__(self, service_key, card_id, user=Ellipsis):
self._service_key = service_key
self._card_id = card_id
self._user = user
self._cached_resultset = None
def _clone(self):
return LazyCardDefObjectsManager(
service_key=self._service_key,
card_id=self._card_id,
user=self._user)
def access_control(self, user):
qs = self._clone()
qs._user = user
return qs
@property
def count(self):
return len(self)
@ -48,12 +61,13 @@ class LazyCardDefObjectsManager(object):
return []
api_url = 'api/cards/%s/list' % self._card_id
without_user = self._user is Ellipsis # not set
try:
response = requests.get(
api_url,
remote_service=service,
user=None,
without_user=True,
user=None if without_user else self._user,
without_user=without_user,
log_errors=False)
response.raise_for_status()
except RequestException:

View File

@ -25,6 +25,11 @@ def objects(cards, slug):
return getattr(cards, slug).objects
@register.filter
def access_control(queryset, user):
return queryset.access_control(user)
@register.filter
def count(queryset):
return queryset.count

View File

@ -6,6 +6,7 @@ import json
import mock
import pytest
from django.template import Context, Template
from django.test.client import RequestFactory
from requests.exceptions import ConnectionError
from requests.models import Response
@ -15,11 +16,36 @@ from combo.apps.wcs.context_processors import Cards
@pytest.fixture
def context():
ctx = Context({
'cards': Cards()
'cards': Cards(),
'request': RequestFactory().get('/'),
})
ctx['request'].user = None
return ctx
class MockAnonymousUser(object):
is_authenticated = False
is_anonymous = True
class MockUser(object):
email = 'foo@example.net'
is_authenticated = True
is_anonymous = False
def get_name_id(self):
return None
class MockUserWithNameId(object):
email = 'foo@example.net'
is_authenticated = True
is_anonymous = False
def get_name_id(self):
return 'xyz'
class MockedRequestResponse(mock.Mock):
status_code = 200
@ -110,6 +136,59 @@ def test_errors(mock_send, context, nocache):
assert t.render(context) == "[]"
@mock.patch('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_access_control(mock_send, context, nocache):
# no user in context
t = Template('{% load wcs %}{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID=&' in mock_send.call_args_list[0][0][0].url
assert 'email=&' in mock_send.call_args_list[0][0][0].url
# current user in anonymous
context['request'].user = MockAnonymousUser()
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID=&' in mock_send.call_args_list[0][0][0].url
assert 'email=&' in mock_send.call_args_list[0][0][0].url
# current user with uuid
context['request'].user = MockUserWithNameId()
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID=xyz&' in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
# current user without uuid
context['request'].user = MockUser()
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email' not in mock_send.call_args_list[0][0][0].url
mock_send.reset_mock()
t = Template('{% load wcs %}{{ cards|objects:"foo"|access_control:request.user|list }}')
t.render(context)
assert 'NameID' not in mock_send.call_args_list[0][0][0].url
assert 'email=foo%40example.net&' in mock_send.call_args_list[0][0][0].url
@mock.patch('combo.apps.wcs.models.requests.send', side_effect=mocked_requests_send)
def test_count(mock_send, context, nocache):
t = Template('{% load wcs %}{{ cards|objects:"foo"|count }}')