This reverts commit a67b9f70a16a0f16a842aad84754b245a2480b5f, reinstating commit cf78660ed35712f9bb7c112f70411179070d7382. The original commit was reverted because I thought I found bugs in it while verifying it on Stage, but it turns out that it was simply misconfigured Stage data that causing errors. The original commit's message has has been copied below: This commit completes the program_enrollments LMS app Python API for the time being. It does the following: * Add bulk-lookup of users by external key in api/reading.py * Add bulk-writing of program enrollments in api/writing.py * Move grade-reading to api/grades.py * Refactor api/linking.py to use api/writing.py * Refactor signals.py to use api/linking.py * Update rest_api/v1/views.py to utilize all these changes * Update linking management command and support tool to use API * Remove outdated tests from test_models.py * Misc. cleanup EDUCATOR-4321
576 lines
22 KiB
Python
576 lines
22 KiB
Python
"""
|
|
Tests for program enrollment reading Python API.
|
|
"""
|
|
from __future__ import absolute_import, unicode_literals
|
|
|
|
from uuid import UUID
|
|
|
|
import ddt
|
|
from django.contrib.auth import get_user_model
|
|
from django.core.cache import cache
|
|
from django.test import TestCase
|
|
from opaque_keys.edx.keys import CourseKey
|
|
from organizations.tests.factories import OrganizationFactory
|
|
from social_django.models import UserSocialAuth
|
|
|
|
from course_modes.models import CourseMode
|
|
from lms.djangoapps.program_enrollments.constants import ProgramCourseEnrollmentStatuses as PCEStatuses
|
|
from lms.djangoapps.program_enrollments.constants import ProgramEnrollmentStatuses as PEStatuses
|
|
from lms.djangoapps.program_enrollments.exceptions import (
|
|
OrganizationDoesNotExistException,
|
|
ProgramDoesNotExistException,
|
|
ProviderConfigurationException,
|
|
ProviderDoesNotExistException
|
|
)
|
|
from lms.djangoapps.program_enrollments.models import ProgramEnrollment
|
|
from lms.djangoapps.program_enrollments.tests.factories import ProgramCourseEnrollmentFactory, ProgramEnrollmentFactory
|
|
from openedx.core.djangoapps.catalog.cache import PROGRAM_CACHE_KEY_TPL
|
|
from openedx.core.djangoapps.catalog.tests.factories import OrganizationFactory as CatalogOrganizationFactory
|
|
from openedx.core.djangoapps.catalog.tests.factories import ProgramFactory
|
|
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
|
|
from openedx.core.djangolib.testing.utils import CacheIsolationTestCase
|
|
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
|
from third_party_auth.tests.factories import SAMLProviderConfigFactory
|
|
|
|
from ..reading import (
|
|
fetch_program_course_enrollments,
|
|
fetch_program_course_enrollments_by_student,
|
|
fetch_program_enrollments,
|
|
fetch_program_enrollments_by_student,
|
|
get_program_course_enrollment,
|
|
get_program_enrollment,
|
|
get_users_by_external_keys
|
|
)
|
|
|
|
User = get_user_model()
|
|
|
|
|
|
@ddt.ddt
|
|
class ProgramEnrollmentReadingTests(TestCase):
|
|
"""
|
|
Tests for program enrollment reading functions.
|
|
"""
|
|
program_uuid_x = UUID('dddddddd-5f48-493d-9410-84e1d36c657f')
|
|
program_uuid_y = UUID('eeeeeeee-f803-43f6-bbf3-5ae15d393649')
|
|
program_uuid_z = UUID('ffffffff-89eb-43df-a6b9-c144e7204fd7') # No enrollments
|
|
curriculum_uuid_a = UUID('aaaaaaaa-bd26-43d0-94b8-b0063858210b')
|
|
curriculum_uuid_b = UUID('bbbbbbbb-145f-43db-ad05-f9ad65eec285')
|
|
curriculum_uuid_c = UUID('cccccccc-4577-4559-85f0-4a83e8160a4d')
|
|
course_key_p = CourseKey.from_string('course-v1:TestX+ProEnroll+P')
|
|
course_key_q = CourseKey.from_string('course-v1:TestX+ProEnroll+Q')
|
|
course_key_r = CourseKey.from_string('course-v1:TestX+ProEnroll+R')
|
|
username_0 = 'user-0'
|
|
username_1 = 'user-1'
|
|
username_2 = 'user-2'
|
|
username_3 = 'user-3'
|
|
username_4 = 'user-4'
|
|
ext_3 = 'student-3'
|
|
ext_4 = 'student-4'
|
|
ext_5 = 'student-5'
|
|
ext_6 = 'student-6'
|
|
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
super(ProgramEnrollmentReadingTests, cls).setUpTestData()
|
|
cls.user_0 = UserFactory(username=cls.username_0) # No enrollments
|
|
cls.user_1 = UserFactory(username=cls.username_1)
|
|
cls.user_2 = UserFactory(username=cls.username_2)
|
|
cls.user_3 = UserFactory(username=cls.username_3)
|
|
cls.user_4 = UserFactory(username=cls.username_4)
|
|
CourseOverviewFactory(id=cls.course_key_p)
|
|
CourseOverviewFactory(id=cls.course_key_q)
|
|
CourseOverviewFactory(id=cls.course_key_r)
|
|
enrollment_test_data = [ # ID
|
|
(cls.user_1, None, cls.program_uuid_x, cls.curriculum_uuid_a, PEStatuses.ENROLLED), # 1
|
|
(cls.user_2, None, cls.program_uuid_x, cls.curriculum_uuid_a, PEStatuses.PENDING), # 2
|
|
(cls.user_3, cls.ext_3, cls.program_uuid_x, cls.curriculum_uuid_b, PEStatuses.ENROLLED), # 3
|
|
(cls.user_4, cls.ext_4, cls.program_uuid_x, cls.curriculum_uuid_b, PEStatuses.PENDING), # 4
|
|
(None, cls.ext_5, cls.program_uuid_x, cls.curriculum_uuid_b, PEStatuses.SUSPENDED), # 5
|
|
(None, cls.ext_6, cls.program_uuid_y, cls.curriculum_uuid_c, PEStatuses.CANCELED), # 6
|
|
(cls.user_3, cls.ext_3, cls.program_uuid_y, cls.curriculum_uuid_c, PEStatuses.CANCELED), # 7
|
|
(None, cls.ext_4, cls.program_uuid_y, cls.curriculum_uuid_c, PEStatuses.ENROLLED), # 8
|
|
(cls.user_1, None, cls.program_uuid_x, cls.curriculum_uuid_b, PEStatuses.SUSPENDED), # 9
|
|
]
|
|
for user, external_user_key, program_uuid, curriculum_uuid, status in enrollment_test_data:
|
|
ProgramEnrollmentFactory(
|
|
user=user,
|
|
external_user_key=external_user_key,
|
|
program_uuid=program_uuid,
|
|
curriculum_uuid=curriculum_uuid,
|
|
status=status,
|
|
)
|
|
course_enrollment_test_data = [ # ID
|
|
(1, cls.course_key_p, PCEStatuses.ACTIVE), # 1
|
|
(1, cls.course_key_q, PCEStatuses.ACTIVE), # 2
|
|
(9, cls.course_key_r, PCEStatuses.ACTIVE), # 3
|
|
(2, cls.course_key_p, PCEStatuses.INACTIVE), # 4
|
|
(3, cls.course_key_p, PCEStatuses.ACTIVE), # 5
|
|
(5, cls.course_key_p, PCEStatuses.INACTIVE), # 6
|
|
(8, cls.course_key_p, PCEStatuses.ACTIVE), # 7
|
|
(8, cls.course_key_q, PCEStatuses.INACTIVE), # 8
|
|
(2, cls.course_key_r, PCEStatuses.INACTIVE), # 9
|
|
(6, cls.course_key_r, PCEStatuses.INACTIVE), # 10
|
|
(8, cls.course_key_r, PCEStatuses.ACTIVE), # 11
|
|
(7, cls.course_key_q, PCEStatuses.ACTIVE), # 12
|
|
|
|
]
|
|
for program_enrollment_id, course_key, status in course_enrollment_test_data:
|
|
program_enrollment = ProgramEnrollment.objects.get(id=program_enrollment_id)
|
|
course_enrollment = (
|
|
CourseEnrollmentFactory(
|
|
course_id=course_key,
|
|
user=program_enrollment.user,
|
|
mode=CourseMode.MASTERS,
|
|
)
|
|
if program_enrollment.user
|
|
else None
|
|
)
|
|
ProgramCourseEnrollmentFactory(
|
|
program_enrollment=program_enrollment,
|
|
course_enrollment=course_enrollment,
|
|
course_key=course_key,
|
|
status=status,
|
|
)
|
|
|
|
@ddt.data(
|
|
# Realized enrollment, specifying only user.
|
|
(program_uuid_x, curriculum_uuid_a, username_1, None, 1),
|
|
|
|
# Realized enrollment, specifiying both user and external key.
|
|
(program_uuid_x, curriculum_uuid_b, username_3, ext_3, 3),
|
|
|
|
# Realized enrollment, specifiying only external key.
|
|
(program_uuid_x, curriculum_uuid_b, None, ext_4, 4),
|
|
|
|
# Waiting enrollment, specifying external key
|
|
(program_uuid_x, curriculum_uuid_b, None, ext_5, 5),
|
|
|
|
# Specifying no curriculum (because ext_6 only has Program Y
|
|
# enrollments in one curriculum, so it's not ambiguous).
|
|
(program_uuid_y, None, None, ext_6, 6),
|
|
)
|
|
@ddt.unpack
|
|
def test_get_program_enrollment(
|
|
self,
|
|
program_uuid,
|
|
curriculum_uuid,
|
|
username,
|
|
external_user_key,
|
|
expected_enrollment_id,
|
|
):
|
|
user = User.objects.get(username=username) if username else None
|
|
actual_enrollment = get_program_enrollment(
|
|
program_uuid=program_uuid,
|
|
curriculum_uuid=curriculum_uuid,
|
|
user=user,
|
|
external_user_key=external_user_key,
|
|
)
|
|
assert actual_enrollment.id == expected_enrollment_id
|
|
|
|
@ddt.data(
|
|
# Realized enrollment, specifying only user.
|
|
(program_uuid_x, None, course_key_p, username_1, None, 1),
|
|
|
|
# Realized enrollment, specifiying both user and external key.
|
|
(program_uuid_x, None, course_key_p, username_3, ext_3, 5),
|
|
|
|
# Realized enrollment, specifiying only external key.
|
|
(program_uuid_y, None, course_key_p, None, ext_4, 7),
|
|
|
|
# Waiting enrollment, specifying external key
|
|
(program_uuid_x, None, course_key_p, None, ext_5, 6),
|
|
|
|
# We can specify curriculum, but it shouldn't affect anything,
|
|
# because each user-course pairing can only have one
|
|
# program-course enrollment.
|
|
(program_uuid_y, curriculum_uuid_c, course_key_r, None, ext_6, 10),
|
|
)
|
|
@ddt.unpack
|
|
def test_get_program_course_enrollment(
|
|
self,
|
|
program_uuid,
|
|
curriculum_uuid,
|
|
course_key,
|
|
username,
|
|
external_user_key,
|
|
expected_enrollment_id,
|
|
):
|
|
user = User.objects.get(username=username) if username else None
|
|
actual_enrollment = get_program_course_enrollment(
|
|
program_uuid=program_uuid,
|
|
curriculum_uuid=curriculum_uuid,
|
|
course_key=course_key,
|
|
user=user,
|
|
external_user_key=external_user_key,
|
|
)
|
|
assert actual_enrollment.id == expected_enrollment_id
|
|
|
|
@ddt.data(
|
|
|
|
# Program with no enrollments
|
|
(
|
|
{'program_uuid': program_uuid_z},
|
|
set(),
|
|
),
|
|
|
|
# Curriculum & status filters
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_x,
|
|
'curriculum_uuids': {curriculum_uuid_a, curriculum_uuid_c},
|
|
'program_enrollment_statuses': {PEStatuses.PENDING, PEStatuses.CANCELED},
|
|
},
|
|
{2},
|
|
),
|
|
|
|
# User & external key filters
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_x,
|
|
'usernames': {username_1, username_2, username_3, username_4},
|
|
'external_user_keys': {ext_3, ext_4, ext_5}
|
|
},
|
|
{3, 4},
|
|
),
|
|
|
|
# Realized-only filter
|
|
(
|
|
{'program_uuid': program_uuid_x, 'realized_only': True},
|
|
{1, 2, 3, 4, 9},
|
|
),
|
|
|
|
# Waiting-only filter
|
|
(
|
|
{'program_uuid': program_uuid_x, 'waiting_only': True},
|
|
{5},
|
|
),
|
|
)
|
|
@ddt.unpack
|
|
def test_fetch_program_enrollments(self, kwargs, expected_enrollment_ids):
|
|
kwargs = self._usernames_to_users(kwargs)
|
|
actual_enrollments = fetch_program_enrollments(**kwargs)
|
|
actual_enrollment_ids = {enrollment.id for enrollment in actual_enrollments}
|
|
assert actual_enrollment_ids == expected_enrollment_ids
|
|
|
|
@ddt.data(
|
|
|
|
# Program with no enrollments
|
|
(
|
|
{'program_uuid': program_uuid_z, 'course_key': course_key_p},
|
|
set(),
|
|
),
|
|
|
|
# Curriculum, status, active-only filters
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_x,
|
|
'course_key': course_key_p,
|
|
'curriculum_uuids': {curriculum_uuid_a, curriculum_uuid_c},
|
|
'program_enrollment_statuses': {PEStatuses.ENROLLED},
|
|
'active_only': True,
|
|
},
|
|
{1},
|
|
),
|
|
|
|
# User and external key filters
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_x,
|
|
'course_key': course_key_p,
|
|
'usernames': {username_2, username_3},
|
|
'external_user_keys': {ext_3, ext_5}
|
|
},
|
|
{5},
|
|
),
|
|
|
|
# Realized-only filter
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_x,
|
|
'course_key': course_key_p,
|
|
'realized_only': True,
|
|
},
|
|
{1, 4, 5},
|
|
),
|
|
|
|
# Waiting-only and inactive-only filters
|
|
(
|
|
{
|
|
'program_uuid': program_uuid_y,
|
|
'course_key': course_key_r,
|
|
'waiting_only': True,
|
|
'inactive_only': True,
|
|
},
|
|
{10},
|
|
),
|
|
)
|
|
@ddt.unpack
|
|
def test_fetch_program_course_enrollments(self, kwargs, expected_enrollment_ids):
|
|
kwargs = self._usernames_to_users(kwargs)
|
|
actual_enrollments = fetch_program_course_enrollments(**kwargs)
|
|
actual_enrollment_ids = {enrollment.id for enrollment in actual_enrollments}
|
|
assert actual_enrollment_ids == expected_enrollment_ids
|
|
|
|
@ddt.data(
|
|
|
|
# User with no enrollments
|
|
(
|
|
{'username': username_0},
|
|
set(),
|
|
),
|
|
|
|
# Filters
|
|
(
|
|
{
|
|
'username': username_3,
|
|
'external_user_key': ext_3,
|
|
'program_uuids': {program_uuid_x},
|
|
'curriculum_uuids': {curriculum_uuid_b, curriculum_uuid_c},
|
|
'program_enrollment_statuses': {PEStatuses.ENROLLED, PEStatuses.CANCELED},
|
|
},
|
|
{3},
|
|
),
|
|
|
|
# More filters
|
|
(
|
|
{
|
|
'username': username_3,
|
|
'external_user_key': ext_3,
|
|
'program_uuids': {program_uuid_x, program_uuid_y},
|
|
'curriculum_uuids': {curriculum_uuid_b, curriculum_uuid_c},
|
|
'program_enrollment_statuses': {PEStatuses.SUSPENDED, PEStatuses.CANCELED},
|
|
},
|
|
{7},
|
|
),
|
|
|
|
# Realized-only filter
|
|
(
|
|
{'external_user_key': ext_4, 'realized_only': True},
|
|
{4},
|
|
),
|
|
|
|
# Waiting-only filter
|
|
(
|
|
{'external_user_key': ext_4, 'waiting_only': True},
|
|
{8},
|
|
),
|
|
)
|
|
@ddt.unpack
|
|
def test_fetch_program_enrollments_by_student(self, kwargs, expected_enrollment_ids):
|
|
kwargs = self._username_to_user(kwargs)
|
|
actual_enrollments = fetch_program_enrollments_by_student(**kwargs)
|
|
actual_enrollment_ids = {enrollment.id for enrollment in actual_enrollments}
|
|
assert actual_enrollment_ids == expected_enrollment_ids
|
|
|
|
@ddt.data(
|
|
|
|
# User with no program enrollments
|
|
(
|
|
{'username': username_0},
|
|
set(),
|
|
),
|
|
|
|
# Course keys and active-only filters
|
|
(
|
|
{
|
|
'external_user_key': ext_4,
|
|
'course_keys': {course_key_p, course_key_q},
|
|
'active_only': True,
|
|
},
|
|
{7},
|
|
),
|
|
|
|
# Curriculum filter
|
|
(
|
|
{'username': username_3, 'curriculum_uuids': {curriculum_uuid_b}},
|
|
{5},
|
|
),
|
|
|
|
# Program filter
|
|
(
|
|
{'username': username_3, 'program_uuids': {program_uuid_y}},
|
|
{12},
|
|
),
|
|
|
|
# Realized-only filter
|
|
(
|
|
{'external_user_key': ext_4, 'realized_only': True},
|
|
set(),
|
|
),
|
|
|
|
# Waiting-only and inactive-only filter
|
|
(
|
|
{
|
|
'external_user_key': ext_4,
|
|
'waiting_only': True,
|
|
'inactive_only': True,
|
|
},
|
|
{8},
|
|
),
|
|
)
|
|
@ddt.unpack
|
|
def test_fetch_program_course_enrollments_by_student(self, kwargs, expected_enrollment_ids):
|
|
kwargs = self._username_to_user(kwargs)
|
|
actual_enrollments = fetch_program_course_enrollments_by_student(**kwargs)
|
|
actual_enrollment_ids = {enrollment.id for enrollment in actual_enrollments}
|
|
assert actual_enrollment_ids == expected_enrollment_ids
|
|
|
|
@staticmethod
|
|
def _username_to_user(dictionary):
|
|
"""
|
|
We can't access the user instances when building `ddt.data`,
|
|
so return a dict with the username swapped out for the user themself.
|
|
"""
|
|
result = dictionary.copy()
|
|
if 'username' in result:
|
|
result['user'] = User.objects.get(username=result['username'])
|
|
del result['username']
|
|
return result
|
|
|
|
@staticmethod
|
|
def _usernames_to_users(dictionary):
|
|
"""
|
|
We can't access the user instances when building `ddt.data`,
|
|
so return a dict with the usernames swapped out for the users themselves.
|
|
"""
|
|
result = dictionary.copy()
|
|
if 'usernames' in result:
|
|
result['users'] = set(
|
|
User.objects.filter(username__in=result['usernames'])
|
|
)
|
|
del result['usernames']
|
|
return result
|
|
|
|
|
|
class GetUsersByExternalKeysTests(CacheIsolationTestCase):
|
|
"""
|
|
Tests for the get_users_by_external_keys function
|
|
"""
|
|
ENABLED_CACHES = ['default']
|
|
|
|
@classmethod
|
|
def setUpTestData(cls):
|
|
super(GetUsersByExternalKeysTests, cls).setUpTestData()
|
|
cls.program_uuid = UUID('e7a82f8d-d485-486b-b733-a28222af92bf')
|
|
cls.organization_key = 'ufo'
|
|
cls.external_user_id = '1234'
|
|
cls.user_0 = UserFactory(username='user-0')
|
|
cls.user_1 = UserFactory(username='user-1')
|
|
cls.user_2 = UserFactory(username='user-2')
|
|
|
|
def setUp(self):
|
|
super(GetUsersByExternalKeysTests, self).setUp()
|
|
catalog_org = CatalogOrganizationFactory.create(key=self.organization_key)
|
|
program = ProgramFactory.create(
|
|
uuid=self.program_uuid,
|
|
authoring_organizations=[catalog_org]
|
|
)
|
|
cache.set(PROGRAM_CACHE_KEY_TPL.format(uuid=self.program_uuid), program, None)
|
|
|
|
def create_social_auth_entry(self, user, provider, external_id):
|
|
"""
|
|
helper functio to create a user social auth entry
|
|
"""
|
|
UserSocialAuth.objects.create(
|
|
user=user,
|
|
uid='{0}:{1}'.format(provider.slug, external_id),
|
|
provider=provider.backend_name,
|
|
)
|
|
|
|
def test_happy_path(self):
|
|
"""
|
|
Test that get_users_by_external_keys returns the expected
|
|
mapping of external keys to users.
|
|
"""
|
|
organization = OrganizationFactory.create(short_name=self.organization_key)
|
|
provider = SAMLProviderConfigFactory.create(organization=organization)
|
|
self.create_social_auth_entry(self.user_0, provider, 'ext-user-0')
|
|
self.create_social_auth_entry(self.user_1, provider, 'ext-user-1')
|
|
self.create_social_auth_entry(self.user_2, provider, 'ext-user-2')
|
|
requested_keys = {'ext-user-1', 'ext-user-2', 'ext-user-3'}
|
|
actual = get_users_by_external_keys(self.program_uuid, requested_keys)
|
|
# ext-user-0 not requested, ext-user-3 doesn't exist
|
|
expected = {
|
|
'ext-user-1': self.user_1,
|
|
'ext-user-2': self.user_2,
|
|
'ext-user-3': None,
|
|
}
|
|
assert actual == expected
|
|
|
|
def test_empty_request(self):
|
|
"""
|
|
Test that requesting no external keys does not cause an exception.
|
|
"""
|
|
organization = OrganizationFactory.create(short_name=self.organization_key)
|
|
SAMLProviderConfigFactory.create(organization=organization)
|
|
actual = get_users_by_external_keys(self.program_uuid, set())
|
|
assert actual == {}
|
|
|
|
def test_catalog_program_does_not_exist(self):
|
|
"""
|
|
Test ProgramDoesNotExistException is thrown if the program cache does
|
|
not include the requested program uuid.
|
|
"""
|
|
fake_program_uuid = UUID('80cc59e5-003e-4664-a582-48da44bc7e12')
|
|
with self.assertRaises(ProgramDoesNotExistException):
|
|
get_users_by_external_keys(fake_program_uuid, [])
|
|
|
|
def test_catalog_program_missing_org(self):
|
|
"""
|
|
Test OrganizationDoesNotExistException is thrown if the cached program does not
|
|
have an authoring organization.
|
|
"""
|
|
program = ProgramFactory.create(
|
|
uuid=self.program_uuid,
|
|
authoring_organizations=[]
|
|
)
|
|
cache.set(PROGRAM_CACHE_KEY_TPL.format(uuid=self.program_uuid), program, None)
|
|
with self.assertRaises(OrganizationDoesNotExistException):
|
|
get_users_by_external_keys(self.program_uuid, [])
|
|
|
|
def test_lms_organization_not_found(self):
|
|
"""
|
|
Test an OrganizationDoesNotExistException is thrown if the LMS has no organization
|
|
matching the catalog program's authoring_organization
|
|
"""
|
|
organization = OrganizationFactory.create(short_name='some_other_org')
|
|
SAMLProviderConfigFactory.create(organization=organization)
|
|
with self.assertRaises(OrganizationDoesNotExistException):
|
|
get_users_by_external_keys(self.program_uuid, [])
|
|
|
|
def test_saml_provider_not_found(self):
|
|
"""
|
|
Test that Prov exception is thrown if no SAML provider exists for this
|
|
program's organization.
|
|
"""
|
|
OrganizationFactory.create(short_name=self.organization_key)
|
|
with self.assertRaises(ProviderDoesNotExistException):
|
|
get_users_by_external_keys(self.program_uuid, [])
|
|
|
|
def test_extra_saml_provider_disabled(self):
|
|
"""
|
|
If multiple samlprovider records exist with the same organization,
|
|
but the extra record is disabled, no exception is raised.
|
|
"""
|
|
organization = OrganizationFactory.create(short_name=self.organization_key)
|
|
SAMLProviderConfigFactory.create(organization=organization)
|
|
# create a second active config for the same organization, NOT enabled
|
|
SAMLProviderConfigFactory.create(
|
|
organization=organization, slug='foox', enabled=False
|
|
)
|
|
get_users_by_external_keys(self.program_uuid, [])
|
|
|
|
def test_extra_saml_provider_enabled(self):
|
|
"""
|
|
If multiple enabled samlprovider records exist with the same organization
|
|
an exception is raised.
|
|
"""
|
|
organization = OrganizationFactory.create(short_name=self.organization_key)
|
|
SAMLProviderConfigFactory.create(organization=organization)
|
|
# create a second active config for the same organizationm, IS enabled
|
|
SAMLProviderConfigFactory.create(
|
|
organization=organization, slug='foox', enabled=True
|
|
)
|
|
with self.assertRaises(ProviderConfigurationException):
|
|
get_users_by_external_keys(self.program_uuid, [])
|