示例#1
0
    def test_get_identity_provider(self):
        """
        Test get_identity_provider returns correct value.
        """
        faker = FakerFactory.create()
        name = faker.name()
        provider_id = faker.slug()  # pylint: disable=no-member

        # test that get_identity_provider returns None if third_party_auth is not available.
        identity_provider = utils.get_identity_provider(
            provider_id=provider_id)
        assert identity_provider is None

        # test that get_identity_provider does not return None if third_party_auth is  available.
        with mock.patch('enterprise.utils.Registry') as mock_registry:
            mock_registry.get.return_value.configure_mock(
                name=name, provider_id=provider_id)
            identity_provider = utils.get_identity_provider(
                provider_id=provider_id)
            assert identity_provider is not None

        # Test that with an invalid provider ID, the function returns None
        with mock.patch('enterprise.utils.Registry') as mock_registry:
            mock_registry.get.side_effect = ValueError
            assert utils.get_identity_provider('bad#$@#$providerid') is None
示例#2
0
文件: forms.py 项目: lxp20201/lxp
    def __init__(self, *args, **kwargs):
        """
        Initialize the form.

        Substitutes CharField with TypedChoiceField for the provider_id field.
        """
        super(EnterpriseCustomerIdentityProviderAdminForm,
              self).__init__(*args, **kwargs)
        idp_choices = utils.get_idp_choices()
        help_text = ''
        if saml_provider_configuration:
            provider_id = self.instance.provider_id
            url = reverse('admin:{}_{}_add'.format(
                saml_provider_configuration._meta.app_label,
                saml_provider_configuration._meta.model_name))
            if provider_id:
                identity_provider = utils.get_identity_provider(provider_id)
                if identity_provider:
                    update_url = url + '?source={}'.format(
                        identity_provider.pk)
                    help_text = '<p><a href="{update_url}" target="_blank">View "{identity_provider}" details</a><p>'.\
                        format(update_url=update_url, identity_provider=identity_provider.name)
                else:
                    help_text += '<p style="margin-top:-5px;"> Make sure you have added a valid provider_id.</p>'
            else:
                help_text += '<p style="margin-top:-5px;"><a target="_blank" href={add_url}>' \
                             'Create a new identity provider</a></p>'.format(add_url=url)

        if idp_choices is not None:
            self.fields['provider_id'] = forms.TypedChoiceField(
                choices=idp_choices,
                label=_('Identity Provider'),
                help_text=mark_safe(help_text),
            )
示例#3
0
    def wrapper(request, *args, **kwargs):
        """
        Wrap the function.
        """
        if not request.GET.get(FRESH_LOGIN_PARAMETER):
            # The enterprise_login_required decorator promises to set the fresh login URL
            # parameter for this URL when it was the agent that initiated the login process;
            # if that parameter isn't set, we can safely assume that the session is "stale";
            # that isn't necessarily an issue, though. Redirect the user to
            # log out and then come back here - the enterprise_login_required decorator will
            # then take effect prior to us arriving back here again.
            enterprise_customer = get_enterprise_customer_or_404(
                kwargs.get('enterprise_uuid'))
            if not enterprise_customer.has_multiple_idps:
                provider_id = enterprise_customer.identity_provider \
                    if enterprise_customer.identity_provider else ''
            else:
                provider_id = ''
            sso_provider = get_identity_provider(provider_id)
            if sso_provider:
                # Parse the current request full path, quote just the path portion,
                # then reconstruct the full path string.
                # The path and query portions should be the only non-empty strings here.
                scheme, netloc, path, params, query, fragment = urlparse(
                    request.get_full_path())
                redirect_url = urlunparse(
                    (scheme, netloc, quote(path), params, query, fragment))

                return redirect('{logout_url}?{params}'.format(
                    logout_url='/logout',
                    params=urlencode({'redirect_url': redirect_url})))
        return view(request, *args, **kwargs)
示例#4
0
    def unlink_learners(self):
        """
        Iterate over each learner and unlink inactive SAP channel learners.

        This method iterates over each enterprise learner and unlink learner
        from the enterprise if the learner is marked inactive in the related
        integrated channel.
        """
        try:
            sap_inactive_learners = self.client.get_inactive_sap_learners()
        except RequestException as exc:
            raise ClientError(
                'SAPSuccessFactorsAPIClient request failed: {error} {message}'.format(
                    error=exc.__class__.__name__,
                    message=str(exc)
                )
            )
        total_sap_inactive_learners = len(sap_inactive_learners) if sap_inactive_learners else 0
        enterprise_customer = self.enterprise_configuration.enterprise_customer
        LOGGER.info(
            'Found [%d] SAP inactive learners for enterprise customer [%s]',
            total_sap_inactive_learners, enterprise_customer.name
        )
        if not sap_inactive_learners:
            return None

        provider_id = enterprise_customer.identity_provider
        tpa_provider = get_identity_provider(provider_id)
        if not tpa_provider:
            LOGGER.info(
                'Enterprise customer [%s] has no associated identity provider',
                enterprise_customer.name
            )
            return None

        for sap_inactive_learner in sap_inactive_learners:
            sap_student_id = sap_inactive_learner['studentID']
            social_auth_user = get_user_from_social_auth(tpa_provider, sap_student_id)
            if not social_auth_user:
                LOGGER.info(
                    'No social auth data found for inactive user with SAP student id [%s] of enterprise '
                    'customer [%s] with identity provider [%s]',
                    sap_student_id, enterprise_customer.name, tpa_provider.provider_id
                )
                continue

            try:
                # Unlink user email from related Enterprise Customer
                EnterpriseCustomerUser.objects.unlink_user(
                    enterprise_customer=enterprise_customer,
                    user_email=social_auth_user.email,
                )
            except (EnterpriseCustomerUser.DoesNotExist, PendingEnterpriseCustomerUser.DoesNotExist):
                LOGGER.info(
                    'Learner with email [%s] and SAP student id [%s] is not linked with enterprise [%s]',
                    social_auth_user.email,
                    sap_student_id,
                    enterprise_customer.name
                )
        return None
def get_user_from_social_auth(tpa_providers, user_id):
    """
    Find the LMS user from the LMS model `UserSocialAuth`.

    Arguments:
        tpa_providers (third_party_auth.provider): list of third party auth provider objects
        user_id (str): User id of user in third party LMS

    """
    providers_backend_names = []
    social_auth_uids = []
    for idp in tpa_providers:
        tpa_provider = get_identity_provider(idp.provider_id)
        # We attach the auth type to the slug at some point in this flow,
        # so to match the original slug, we need to chop off that backend name.
        # We only use saml here, so we are removing the first 5 characters, ie 'saml-'
        provider_slug = tpa_provider.provider_id[5:]
        social_auth_uid = '{0}:{1}'.format(provider_slug, user_id)
        providers_backend_names.append(tpa_provider.backend_name)
        social_auth_uids.append(social_auth_uid)
    # we are filtering by both `provider` and `uid` to make use of provider,uid composite index
    # filtering only on `uid` makes query extremely slow since we don't have index on `uid`
    user_social_auth = UserSocialAuth.objects.select_related('user').filter(
        provider__in=providers_backend_names, uid__in=social_auth_uids
    ).first()

    return user_social_auth.user if user_social_auth else None
    def test_get_identity_provider(self):
        """
        Test get_identity_provider returns correct value.
        """
        faker = FakerFactory.create()
        name = faker.name()
        provider_id = faker.slug()

        # test that get_identity_provider returns None if third_party_auth is not available.
        identity_provider = utils.get_identity_provider(
            provider_id=provider_id)
        assert identity_provider is None

        # test that get_identity_provider does not return None if third_party_auth is  available.
        with mock.patch('enterprise.utils.Registry') as mock_registry:
            mock_registry.get.return_value.configure_mock(
                name=name, provider_id=provider_id)
            identity_provider = utils.get_identity_provider(
                provider_id=provider_id)
            assert identity_provider is not None
示例#7
0
def get_user_social_auth(user, enterprise_customer):
    """
    Return social auth entry of user for given enterprise.

    Arguments:
        user (User): user object
        enterprise_customer (EnterpriseCustomer): User id of user in third party LMS

    """
    provider_id = enterprise_customer.identity_provider
    tpa_provider = get_identity_provider(provider_id)
    user_social_auth = UserSocialAuth.objects.filter(
        user=user, provider=tpa_provider.backend_name).first()

    return user_social_auth
def get_user_social_auth(user, enterprise_customer):
    """
    Return social auth entry of user for given enterprise.

    Arguments:
        user (User): user object
        enterprise_customer (EnterpriseCustomer): User id of user in third party LMS

    """
    provider_backend_names = []
    for idp in enterprise_customer.identity_providers:
        tpa_provider = get_identity_provider(idp.provider_id)
        provider_backend_names.append(tpa_provider.backend_name)
    user_social_auth = UserSocialAuth.objects.filter(provider__in=provider_backend_names, user=user).first()

    return user_social_auth
示例#9
0
    def clean(self):
        """
        Final validations of model fields.

        1. Validate that selected site for enterprise customer matches with the selected identity provider's site.
        """
        super(EnterpriseCustomerIdentityProviderAdminForm, self).clean()

        provider_id = self.cleaned_data.get('provider_id', None)
        enterprise_customer = self.cleaned_data.get('enterprise_customer', None)

        if provider_id is None or enterprise_customer is None:
            # field validation for either provider_id or enterprise_customer has already raised
            # a validation error.
            return

        identity_provider = utils.get_identity_provider(provider_id)
        if not identity_provider:
            # This should not happen, as identity providers displayed in drop down are fetched dynamically.
            message = _(
                "The specified Identity Provider does not exist. For more "
                "information, contact a system administrator.",
            )
            # Log message for debugging
            logger.exception(message)

            raise ValidationError(message)

        if identity_provider and identity_provider.site != enterprise_customer.site:
            raise ValidationError(
                _(
                    "The site for the selected identity provider "
                    "({identity_provider_site}) does not match the site for "
                    "this enterprise customer ({enterprise_customer_site}). "
                    "To correct this problem, select a site that has a domain "
                    "of '{identity_provider_site}', or update the identity "
                    "provider to '{enterprise_customer_site}'."
                ).format(
                    enterprise_customer_site=enterprise_customer.site,
                    identity_provider_site=identity_provider.site,
                ),
            )
示例#10
0
    def clean(self):
        """
        Final validations of model fields.

        1. Validate that selected site for enterprise customer matches with the selected identity provider's site.
        """
        super(EnterpriseCustomerIdentityProviderAdminForm, self).clean()

        provider_id = self.cleaned_data.get('provider_id', None)
        enterprise_customer = self.cleaned_data.get('enterprise_customer', None)

        if provider_id is None or enterprise_customer is None:
            # field validation for either provider_id or enterprise_customer has already raised
            # a validation error.
            return
        try:
            identity_provider = utils.get_identity_provider(provider_id)
        except ObjectDoesNotExist:
            # This should not happen, as identity providers displayed in drop down are fetched dynamically.
            message = _(
                "Selected Identity Provider does not exist, please contact system administrator for more info.",
            )
            # Log message for debugging
            logger.exception(message)

            raise ValidationError(message)

        if identity_provider and identity_provider.site != enterprise_customer.site:
            raise ValidationError(
                _(
                    "Site ({identity_provider_site}) of selected identity provider does not match with "
                    "enterprise customer's site ({enterprise_customer_site})."
                    "Please either select site with domain '{identity_provider_site}' or update identity provider's "
                    "site to '{enterprise_customer_site}'."
                ).format(
                    enterprise_customer_site=enterprise_customer.site,
                    identity_provider_site=identity_provider.site,
                ),
            )
示例#11
0
 def provider_name(self):
     """
     Readable name for the identity provider.
     """
     identity_provider = utils.get_identity_provider(self.provider_id)
     return identity_provider and identity_provider.name