Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion openedx/core/djangoapps/appsembler/api/tests/test_user_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
@mock.patch(APPSEMBLER_API_VIEWS_MODULE + '.UserIndexViewSet.throttle_classes', [])
class UserIndexViewSetTest(TestCase):

# Fixtures to be used for filtering
JANE_DUE_USERNAME = 'jane.due'
JANE_DUE_EMAIL = '{username}@user.api.example.com'.format(username=JANE_DUE_USERNAME)
NON_USER_EMAIL = 'not.for.a.user@user.api.example.com'

def setUp(self):
"""
Set up test data for site isolation
Expand All @@ -51,7 +56,12 @@ def setUp(self):
self.my_site_org = OrganizationFactory(sites=[self.my_site])

# Set up users and enrollments for 'my site'
self.my_site_users = [UserFactory() for i in range(3)]
self.my_site_users = [
UserFactory.create(email=self.JANE_DUE_EMAIL, username=self.JANE_DUE_USERNAME),
UserFactory.create(),
UserFactory.create(),
]

for user in self.my_site_users:
UserOrganizationMappingFactory(user=user,
organization=self.my_site_org)
Expand Down Expand Up @@ -90,6 +100,32 @@ def test_get_all_users_for_site(self):
user_ids = [rec['id'] for rec in results]
assert set(user_ids) == set([obj.id for obj in expected_users])

@ddt.unpack
@ddt.data(
{'email': JANE_DUE_EMAIL.lower(), 'expected_count': 1, 'msg': 'Should find Jane (lower case) in the users'},
{'email': JANE_DUE_EMAIL.upper(), 'expected_count': 1, 'msg': 'Should find Jane (upper case) in the users'},
{'email': JANE_DUE_USERNAME, 'expected_count': 0, 'msg': 'Should not do partial matching'},
{'email': NON_USER_EMAIL, 'expected_count': 0, 'msg': 'Should not match any user.'},
)
def test_filter_by_email(self, email, expected_count, msg):
"""
Test the email filters matching.
"""
url = reverse('tahoe-api:v1:users-list')
request = APIRequestFactory().get(url, {'email_exact': email})
request.META['HTTP_HOST'] = self.my_site.domain
force_authenticate(request, user=self.caller)

view = resolve(url).func
response = view(request)
response.render()
results = response.data['results']

assert len(results) == expected_count, msg
if expected_count:
# Ignore the email case
assert results[0]['email'].lower() == email.lower(), msg

@skip("Need to implement user filter")
def test_get_all_enrolled_learners_for_site(self):

Expand Down
13 changes: 13 additions & 0 deletions openedx/core/djangoapps/appsembler/api/v1/filters.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

import django_filters
from django.contrib.auth import get_user_model
from opaque_keys.edx.keys import CourseKey
from openedx.core.djangoapps.content.course_overviews.models import (
CourseOverview,
Expand Down Expand Up @@ -68,3 +69,15 @@ def filter_course_id(self, queryset, name, value):
class Meta:
model = CourseEnrollment
fields = ['course_id', 'user_id', 'username', 'is_active', ]


class UserIndexFilter(django_filters.FilterSet):
'''Provides filtering for the User model objects in the UserIndexViewSet.

'''

email_exact = django_filters.CharFilter(name='email', lookup_expr='iexact')

class Meta:
model = get_user_model()
fields = ['email_exact']
4 changes: 3 additions & 1 deletion openedx/core/djangoapps/appsembler/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@
from openedx.core.djangoapps.appsembler.api.v1.api import enroll_learners_in_course
from openedx.core.djangoapps.appsembler.api.v1.filters import (
CourseEnrollmentFilter,
CourseOverviewFilter
CourseOverviewFilter,
UserIndexFilter,
)
from openedx.core.djangoapps.appsembler.api.v1.pagination import (
TahoeLimitOffsetPagination
Expand Down Expand Up @@ -397,6 +398,7 @@ class UserIndexViewSet(TahoeAuthMixin, viewsets.ReadOnlyModelViewSet):
serializer_class = UserIndexSerializer
throttle_classes = (TahoeAPIUserThrottle,)
filter_backends = (DjangoFilterBackend, )
filter_class = UserIndexFilter

def get_queryset(self):
site = django.contrib.sites.shortcuts.get_current_site(self.request)
Expand Down