Beispiel #1
0
    def inner(request, *args, **kwargs):
        """
        Check for a TPA hint in combination with a logged in user, and log the user out
        if the hinted provider specifies that they should be, and if they haven't already
        been redirected to a logout by this decorator.
        """
        sso_provider = None
        provider_id = request.GET.get('tpa_hint')
        decorator_already_processed = request.GET.get(
            'session_cleared') == 'yes'
        if provider_id and not decorator_already_processed:
            # Check that there is a provider and that we haven't already processed this view.
            if request.user and request.user.is_authenticated():
                try:
                    sso_provider = Registry.get(provider_id=provider_id)
                except ValueError:
                    sso_provider = None
        if sso_provider and sso_provider.drop_existing_session:
            # Do the redirect only if the configured provider says we ought to.
            return redirect('{}?{}'.format(
                request.build_absolute_uri(reverse('logout')),
                urlencode({
                    'redirect_url':
                    '{}?{}'.format(
                        request.path,
                        urlencode([('tpa_hint', provider_id),
                                   ('session_cleared', 'yes')]))
                })))

        else:
            # Otherwise, pass everything through to the wrapped view.
            return func(request, *args, **kwargs)
Beispiel #2
0
def enterprise_customer_for_request(request, tpa_hint=None):
    """
    Check all the context clues of the request to determine if
    the request being made is tied to a particular EnterpriseCustomer.
    """
    if not enterprise_enabled():
        return None

    ec = None

    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the tpa_hint parameter to match if so.
        tpa_hint = Registry.get_from_pipeline(running_pipeline).provider_id

    if tpa_hint:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            ec = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=tpa_hint)
        except EnterpriseCustomer.DoesNotExist:
            pass

    ec_uuid = request.GET.get('enterprise_customer') or request.COOKIES.get(
        settings.ENTERPRISE_CUSTOMER_COOKIE_NAME)
    # If we haven't obtained an EnterpriseCustomer through the other methods, check the
    # session cookies and URL parameters for an explicitly-passed EnterpriseCustomer.
    if not ec and ec_uuid:
        try:
            ec = EnterpriseCustomer.objects.get(uuid=ec_uuid)
        except (EnterpriseCustomer.DoesNotExist, ValueError):
            ec = None

    return ec
Beispiel #3
0
    def get_queryset(self):
        provider_id = self.kwargs.get('provider_id')

        # provider existence checking
        self.provider = Registry.get(provider_id)
        if not self.provider:
            raise Http404

        query_set = filter_user_social_auth_queryset_by_provider(
            UserSocialAuth.objects.select_related('user'),
            self.provider,
        )
        query = Q()

        usernames = self.request.query_params.getlist('username', None)
        remote_ids = self.request.query_params.getlist('remote_id', None)

        if usernames:
            usernames = ','.join(usernames)
            usernames = set(usernames.split(',')) if usernames else set()
            if usernames:
                query = query | Q(user__username__in=usernames)

        if remote_ids:
            remote_ids = ','.join(remote_ids)
            remote_ids = set(remote_ids.split(',')) if remote_ids else set()
            if remote_ids:
                query = query | Q(uid__in=[
                    self.provider.get_social_auth_uid(remote_id)
                    for remote_id in remote_ids
                ])

        return query_set.filter(query)
Beispiel #4
0
def unlink_enterprise_user_from_idp(request, user, idp_backend_name):
    """
    Un-links learner from their enterprise identity provider
    Args:
        request (wsgi request): request object
        user (User): user who initiated disconnect request
        idp_backend_name (str): Name of identity provider's backend

    Returns: None

    """
    enterprise_customer = enterprise_customer_for_request(request)
    if user and enterprise_customer:
        enabled_providers = Registry.get_enabled_by_backend_name(idp_backend_name)
        provider_ids = [enabled_provider.provider_id for enabled_provider in enabled_providers]
        enterprise_customer_idps = EnterpriseCustomerIdentityProvider.objects.filter(
            enterprise_customer__uuid=enterprise_customer['uuid'],
            provider_id__in=provider_ids
        )

        if enterprise_customer_idps:
            try:
                # Unlink user email from each Enterprise Customer.
                for enterprise_customer_idp in enterprise_customer_idps:
                    EnterpriseCustomerUser.objects.unlink_user(
                        enterprise_customer=enterprise_customer_idp.enterprise_customer, user_email=user.email
                    )
            except (EnterpriseCustomerUser.DoesNotExist, PendingEnterpriseCustomerUser.DoesNotExist):
                pass
Beispiel #5
0
def get_enterprise_customer_for_running_pipeline(request, pipeline):  # pylint: disable=invalid-name
    """
    Get the EnterpriseCustomer associated with a running pipeline.
    """
    sso_provider_id = request.GET.get('tpa_hint')
    if pipeline:
        sso_provider_id = Registry.get_from_pipeline(pipeline).provider_id
    return get_enterprise_customer_for_sso(sso_provider_id)
Beispiel #6
0
def get_enterprise_customer_for_running_pipeline(pipeline):  # pylint: disable=invalid-name
    """
    Get the EnterpriseCustomer associated with a running pipeline.
    """
    verify_third_party_auth_dependencies()
    if pipeline is None:
        return None
    provider = Registry.get_from_pipeline(pipeline)
    return get_enterprise_customer_for_sso(provider)
Beispiel #7
0
def enterprise_customer_for_request(request):
    """
    Check all the context clues of the request to determine if
    the request being made is tied to a particular EnterpriseCustomer.
    """

    if not enterprise_enabled():
        return None

    ec = None
    sso_provider_id = request.GET.get('tpa_hint')

    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the sso_provider_id parameter to match if so.
        sso_provider_id = Registry.get_from_pipeline(
            running_pipeline).provider_id

    if sso_provider_id:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            # FIXME: Implement an Enterprise API endpoint where we can get the EC
            # directly via the linked SSO provider
            # Check if there's an Enterprise Customer such that the linked SSO provider
            # has an ID equal to the ID we got from the running pipeline or from the
            # request tpa_hint URL parameter.
            ec_uuid = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=
                sso_provider_id).uuid
        except EnterpriseCustomer.DoesNotExist:
            # If there is not an EnterpriseCustomer linked to this SSO provider, set
            # the UUID variable to be null.
            ec_uuid = None
    else:
        # Check if we got an Enterprise UUID passed directly as either a query
        # parameter, or as a value in the Enterprise cookie.
        ec_uuid = request.GET.get(
            'enterprise_customer') or request.COOKIES.get(
                settings.ENTERPRISE_CUSTOMER_COOKIE_NAME)

    if not ec_uuid and request.user.is_authenticated():
        # If there's no way to get an Enterprise UUID for the request, check to see
        # if there's already an Enterprise attached to the requesting user on the backend.
        learner_data = get_enterprise_learner_data(request.site, request.user)
        if learner_data:
            ec_uuid = learner_data[0]['enterprise_customer']['uuid']
    if ec_uuid:
        # If we were able to obtain an EnterpriseCustomer UUID, go ahead
        # and use it to attempt to retrieve EnterpriseCustomer details
        # from the EnterpriseCustomer API.
        try:
            ec = EnterpriseApiClient().get_enterprise_customer(ec_uuid)
        except HttpNotFoundError:
            ec = None

    return ec
Beispiel #8
0
def get_identity_provider(provider_id):
    """
    Get Identity Provider with given id.

    Raises a ValueError if it third_party_auth app is not available.

    Return:
        Instance of ProviderConfig or None.
    """
    return Registry and Registry.get(provider_id)
Beispiel #9
0
def get_identity_provider(provider_id):
    """
    Get Identity Provider with given id.

    Return:
        Instance of ProviderConfig or None.
    """
    try:
        return Registry and Registry.get(provider_id)
    except ValueError:
        return None
Beispiel #10
0
def enterprise_customer_for_request(request):
    """
    Check all the context clues of the request to determine if
    the request being made is tied to a particular EnterpriseCustomer.
    """

    if not enterprise_enabled():
        return None

    ec = None
    sso_provider_id = request.GET.get('tpa_hint')

    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the sso_provider_id parameter to match if so.
        sso_provider_id = Registry.get_from_pipeline(running_pipeline).provider_id

    if sso_provider_id:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            # FIXME: Implement an Enterprise API endpoint where we can get the EC
            # directly via the linked SSO provider
            # Check if there's an Enterprise Customer such that the linked SSO provider
            # has an ID equal to the ID we got from the running pipeline or from the
            # request tpa_hint URL parameter.
            ec_uuid = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=sso_provider_id
            ).uuid
        except EnterpriseCustomer.DoesNotExist:
            # If there is not an EnterpriseCustomer linked to this SSO provider, set
            # the UUID variable to be null.
            ec_uuid = None
    else:
        # Check if we got an Enterprise UUID passed directly as either a query
        # parameter, or as a value in the Enterprise cookie.
        ec_uuid = request.GET.get('enterprise_customer') or request.COOKIES.get(settings.ENTERPRISE_CUSTOMER_COOKIE_NAME)

    if not ec_uuid and request.user.is_authenticated():
        # If there's no way to get an Enterprise UUID for the request, check to see
        # if there's already an Enterprise attached to the requesting user on the backend.
        learner_data = get_enterprise_learner_data(request.site, request.user)
        if learner_data:
            ec_uuid = learner_data[0]['enterprise_customer']['uuid']
    if ec_uuid:
        # If we were able to obtain an EnterpriseCustomer UUID, go ahead
        # and use it to attempt to retrieve EnterpriseCustomer details
        # from the EnterpriseCustomer API.
        try:
            ec = EnterpriseApiClient().get_enterprise_customer(ec_uuid)
        except HttpNotFoundError:
            ec = None

    return ec
Beispiel #11
0
def get_idp_choices():
    """
    Get a list of identity providers choices for enterprise customer.

    Return:
        A list of choices of all identity providers, None if it can not get any available identity provider.
    """
    first = [("", "-"*7)]
    if Registry:
        return first + [(idp.provider_id, idp.name) for idp in Registry.enabled()]
    else:
        return None
Beispiel #12
0
def get_ec_for_running_pipeline(pipeline):
    """
    Get the EnterpriseCustomer associated with a running pipeline.
    """
    if Registry is None:
        raise NotConnectedToEdX(
            _("This package must be installed in an EdX environment to look up third-party auth providers."
              ))

    if pipeline is None:
        return None
    provider = Registry.get_from_pipeline(pipeline)
    return get_enterprise_customer_for_sso(provider)
Beispiel #13
0
def enterprise_customer_uuid_for_request(request):
    """
    Check all the context clues of the request to gather a particular EnterpriseCustomer's UUID.
    """
    sso_provider_id = request.GET.get('tpa_hint')
    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the sso_provider_id parameter to match if so.
        sso_provider_id = Registry.get_from_pipeline(
            running_pipeline).provider_id

    if sso_provider_id:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            # FIXME: Implement an Enterprise API endpoint where we can get the EC
            # directly via the linked SSO provider
            # Check if there's an Enterprise Customer such that the linked SSO provider
            # has an ID equal to the ID we got from the running pipeline or from the
            # request tpa_hint URL parameter.
            enterprise_customer_uuid = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=
                sso_provider_id).uuid
        except EnterpriseCustomer.DoesNotExist:
            enterprise_customer_uuid = None
    else:
        enterprise_customer_uuid = _customer_uuid_from_query_param_cookies_or_session(
            request)

    if enterprise_customer_uuid is _CACHE_MISS:
        if not request.user.is_authenticated:
            return None

        # If there's no way to get an Enterprise UUID for the request, check to see
        # if there's already an Enterprise attached to the requesting user on the backend.
        enterprise_customer = None
        learner_data = get_enterprise_learner_data_from_db(request.user)
        if learner_data:
            enterprise_customer = learner_data[0]['enterprise_customer']
            enterprise_customer_uuid = enterprise_customer['uuid']
            cache_enterprise(enterprise_customer)
        else:
            enterprise_customer_uuid = None

        # Now that we've asked the database for this users's enterprise customer data,
        # add it to their session (even if it's null/empty, which indicates the user
        # has no associated enterprise customer).
        add_enterprise_customer_to_session(request, enterprise_customer)

    return enterprise_customer_uuid
Beispiel #14
0
    def get_queryset(self):
        provider_id = self.kwargs.get('provider_id')

        # permission checking. We allow both API_KEY access and OAuth2 client credential access
        if not (self.request.user.is_superuser
                or ApiKeyHeaderPermission().has_permission(self.request, self)
                or ThirdPartyAuthProviderApiPermission(
                    provider_id).has_permission(self.request, self)):
            raise exceptions.PermissionDenied()

        # provider existence checking
        self.provider = Registry.get(provider_id)
        if not self.provider:
            raise Http404

        query_set = UserSocialAuth.objects.select_related('user').filter(
            provider=self.provider.backend_name)

        # build our query filters
        # When using multi-IdP backend, we only retrieve the ones that are for current IdP.
        # test if the current provider has a slug
        uid = self.provider.get_social_auth_uid('uid')
        if uid != 'uid':
            # if yes, we add a filter for the slug on uid column
            query_set = query_set.filter(uid__startswith=uid[:-3])

        query = Q()

        usernames = self.request.query_params.getlist('username', None)
        remote_ids = self.request.query_params.getlist('remote_id', None)

        if usernames:
            usernames = ','.join(usernames)
            usernames = set(usernames.split(',')) if usernames else set()
            if usernames:
                query = query | Q(user__username__in=usernames)

        if remote_ids:
            remote_ids = ','.join(remote_ids)
            remote_ids = set(remote_ids.split(',')) if remote_ids else set()
            if remote_ids:
                query = query | Q(uid__in=[
                    self.provider.get_social_auth_uid(remote_id)
                    for remote_id in remote_ids
                ])

        return query_set.filter(query)
Beispiel #15
0
def get_identity_provider(provider_id):
    """
    Get Identity Provider with given id.

    Return:
        Instance of ProviderConfig or None.
    """
    try:
        from third_party_auth.provider import Registry   # pylint: disable=redefined-outer-name
    except ImportError as exception:
        LOGGER.warning("Could not import Registry from third_party_auth.provider")
        LOGGER.warning(exception)
        Registry = None  # pylint: disable=redefined-outer-name

    try:
        return Registry and Registry.get(provider_id)
    except ValueError:
        return None
Beispiel #16
0
def get_idp_choices():
    """
    Get a list of identity providers choices for enterprise customer.

    Return:
        A list of choices of all identity providers, None if it can not get any available identity provider.
    """
    try:
        from third_party_auth.provider import Registry   # pylint: disable=redefined-outer-name
    except ImportError as exception:
        LOGGER.warning("Could not import Registry from third_party_auth.provider")
        LOGGER.warning(exception)
        Registry = None  # pylint: disable=redefined-outer-name

    first = [("", "-" * 7)]
    if Registry:
        return first + [(idp.provider_id, idp.name) for idp in Registry.enabled()]
    return None
Beispiel #17
0
    def get_queryset(self):
        provider_id = self.kwargs.get('provider_id')

        # permission checking. We allow both API_KEY access and OAuth2 client credential access
        if not (
                self.request.user.is_superuser or ApiKeyHeaderPermission().has_permission(self.request, self) or
                ThirdPartyAuthProviderApiPermission(provider_id).has_permission(self.request, self)
        ):
            raise exceptions.PermissionDenied()

        # provider existence checking
        self.provider = Registry.get(provider_id)
        if not self.provider:
            raise Http404

        query_set = UserSocialAuth.objects.select_related('user').filter(provider=self.provider.backend_name)

        # build our query filters
        # When using multi-IdP backend, we only retrieve the ones that are for current IdP.
        # test if the current provider has a slug
        uid = self.provider.get_social_auth_uid('uid')
        if uid != 'uid':
            # if yes, we add a filter for the slug on uid column
            query_set = query_set.filter(uid__startswith=uid[:-3])

        query = Q()

        usernames = self.request.query_params.getlist('username', None)
        remote_ids = self.request.query_params.getlist('remote_id', None)

        if usernames:
            usernames = ','.join(usernames)
            usernames = set(usernames.split(',')) if usernames else set()
            if usernames:
                query = query | Q(user__username__in=usernames)

        if remote_ids:
            remote_ids = ','.join(remote_ids)
            remote_ids = set(remote_ids.split(',')) if remote_ids else set()
            if remote_ids:
                query = query | Q(uid__in=[self.provider.get_social_auth_uid(remote_id) for remote_id in remote_ids])

        return query_set.filter(query)
Beispiel #18
0
def enterprise_customer_uuid_for_request(request):
    """
    Check all the context clues of the request to gather a particular EnterpriseCustomer's UUID.
    """
    sso_provider_id = request.GET.get('tpa_hint')
    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the sso_provider_id parameter to match if so.
        sso_provider_id = Registry.get_from_pipeline(
            running_pipeline).provider_id

    if sso_provider_id:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            # FIXME: Implement an Enterprise API endpoint where we can get the EC
            # directly via the linked SSO provider
            # Check if there's an Enterprise Customer such that the linked SSO provider
            # has an ID equal to the ID we got from the running pipeline or from the
            # request tpa_hint URL parameter.
            enterprise_customer_uuid = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=
                sso_provider_id).uuid
        except EnterpriseCustomer.DoesNotExist:
            enterprise_customer_uuid = None
    else:
        # Check if we got an Enterprise UUID passed directly as either a query
        # parameter, or as a value in the Enterprise cookie.
        enterprise_customer_uuid = request.GET.get(
            'enterprise_customer') or request.COOKIES.get(
                settings.ENTERPRISE_CUSTOMER_COOKIE_NAME)

    if not enterprise_customer_uuid and request.user.is_authenticated:
        # If there's no way to get an Enterprise UUID for the request, check to see
        # if there's already an Enterprise attached to the requesting user on the backend.
        learner_data = get_enterprise_learner_data(request.user)
        if learner_data:
            enterprise_customer_uuid = learner_data[0]['enterprise_customer'][
                'uuid']

    return enterprise_customer_uuid
    def handle(self, *args, **options):
        provider_slug = options.get('provider_slug', None)

        try:
            provider = Registry.get(provider_slug)
        except ValueError as e:
            raise CommandError('provider slug {slug} does not exist'.format(slug=provider_slug))

        query_set = UserSocialAuth.objects.select_related('user__profile')
        query_set = filter_user_social_auth_queryset_by_provider(query_set, provider)
        query_set = self.filter_user_social_auth_queryset_by_ssoverification_existence(query_set)
        for user_social_auth in query_set:
            verification = SSOVerification.objects.create(
                user=user_social_auth.user,
                status="approved",
                name=user_social_auth.user.profile.name,
                identity_provider_type=provider.full_class_name,
                identity_provider_slug=provider.slug,
            )
            # Send a signal so users who have already passed their courses receive credit
            verification.send_approval_signal(provider.slug)
    def inner(request, *args, **kwargs):
        """
        Check for a TPA hint in combination with a logged in user, and log the user out
        if the hinted provider specifies that they should be, and if they haven't already
        been redirected to a logout by this decorator.
        """
        sso_provider = None
        provider_id = request.GET.get('tpa_hint')
        decorator_already_processed = request.GET.get('session_cleared') == 'yes'
        if provider_id and not decorator_already_processed:
            # Check that there is a provider and that we haven't already processed this view.
            if request.user and request.user.is_authenticated():
                try:
                    sso_provider = Registry.get(provider_id=provider_id)
                except ValueError:
                    sso_provider = None
        if sso_provider and sso_provider.drop_existing_session:
            # Do the redirect only if the configured provider says we ought to.
            return redirect(
                '{}?{}'.format(
                    request.build_absolute_uri(reverse('logout')),
                    urlencode(
                        {
                            'redirect_url': '{}?{}'.format(
                                request.path,
                                urlencode(
                                    [
                                        ('tpa_hint', provider_id),
                                        ('session_cleared', 'yes')
                                    ]
                                )
                            )
                        }
                    )
                )
            )

        else:
            # Otherwise, pass everything through to the wrapped view.
            return func(request, *args, **kwargs)
Beispiel #21
0
    def get_queryset(self):
        provider_id = self.kwargs.get('provider_id')

        # provider existence checking
        self.provider = Registry.get(provider_id)
        if not self.provider:
            raise Http404

        query_set = UserSocialAuth.objects.select_related('user').filter(
            provider=self.provider.backend_name)

        # build our query filters
        # When using multi-IdP backend, we only retrieve the ones that are for current IdP.
        # test if the current provider has a slug
        uid = self.provider.get_social_auth_uid('uid')
        if uid != 'uid':
            # if yes, we add a filter for the slug on uid column
            query_set = query_set.filter(uid__startswith=uid[:-3])

        query = Q()

        usernames = self.request.query_params.getlist('username', None)
        remote_ids = self.request.query_params.getlist('remote_id', None)

        if usernames:
            usernames = ','.join(usernames)
            usernames = set(usernames.split(',')) if usernames else set()
            if usernames:
                query = query | Q(user__username__in=usernames)

        if remote_ids:
            remote_ids = ','.join(remote_ids)
            remote_ids = set(remote_ids.split(',')) if remote_ids else set()
            if remote_ids:
                query = query | Q(uid__in=[
                    self.provider.get_social_auth_uid(remote_id)
                    for remote_id in remote_ids
                ])

        return query_set.filter(query)
Beispiel #22
0
def enterprise_customer_uuid_for_request(request):
    """
    Check all the context clues of the request to gather a particular EnterpriseCustomer's UUID.
    """
    sso_provider_id = request.GET.get('tpa_hint')
    running_pipeline = get_partial_pipeline(request)
    if running_pipeline:
        # Determine if the user is in the middle of a third-party auth pipeline,
        # and set the sso_provider_id parameter to match if so.
        sso_provider_id = Registry.get_from_pipeline(running_pipeline).provider_id

    if sso_provider_id:
        # If we have a third-party auth provider, get the linked enterprise customer.
        try:
            # FIXME: Implement an Enterprise API endpoint where we can get the EC
            # directly via the linked SSO provider
            # Check if there's an Enterprise Customer such that the linked SSO provider
            # has an ID equal to the ID we got from the running pipeline or from the
            # request tpa_hint URL parameter.
            enterprise_customer_uuid = EnterpriseCustomer.objects.get(
                enterprise_customer_identity_provider__provider_id=sso_provider_id
            ).uuid
        except EnterpriseCustomer.DoesNotExist:
            enterprise_customer_uuid = None
    else:
        # Check if we got an Enterprise UUID passed directly as either a query
        # parameter, or as a value in the Enterprise cookie.
        enterprise_customer_uuid = request.GET.get('enterprise_customer') or request.COOKIES.get(
            settings.ENTERPRISE_CUSTOMER_COOKIE_NAME
        )

    if not enterprise_customer_uuid and request.user.is_authenticated:
        # If there's no way to get an Enterprise UUID for the request, check to see
        # if there's already an Enterprise attached to the requesting user on the backend.
        learner_data = get_enterprise_learner_data(request.user)
        if learner_data:
            enterprise_customer_uuid = learner_data[0]['enterprise_customer']['uuid']

    return enterprise_customer_uuid
Beispiel #23
0
 def __init__(self, *args, **kwargs):
     super(ApiPermissionsAdminForm, self).__init__(*args, **kwargs)
     self.fields['provider_id'].choices = (
         (provider.provider_id, "{} ({})".format(provider.name,
                                                 provider.provider_id))
         for provider in Registry.enabled())
Beispiel #24
0
 def __init__(self, *args, **kwargs):
     super(ApiPermissionsAdminForm, self).__init__(*args, **kwargs)
     self.fields['provider_id'].choices = (
         (provider.provider_id, "{} ({})".format(provider.name, provider.provider_id))
         for provider in Registry.enabled()
     )