Add API view for retrieving third party auth user status.

This commit is contained in:
Douglas Hall
2019-04-01 10:55:29 -04:00
parent 5462474aa6
commit 7128059921
3 changed files with 91 additions and 2 deletions

View File

@@ -351,3 +351,35 @@ class UserMappingViewAPITests(TpaAPITestCase):
for item in ['results', 'count', 'num_pages']:
self.assertIn(item, response.data)
self.assertItemsEqual(response.data['results'], expect_result)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
class TestThirdPartyAuthUserStatusView(ThirdPartyAuthTestMixin, APITestCase):
"""
Tests ThirdPartyAuthStatusView.
"""
def setUp(self, *args, **kwargs):
super(TestThirdPartyAuthUserStatusView, self).setUp(*args, **kwargs)
self.user = UserFactory.create(password=PASSWORD)
self.google_provider = self.configure_google_provider(enabled=True, visible=True)
self.url = reverse('third_party_auth_user_status_api')
def test_get(self):
"""
Verify that get returns the expected data.
"""
self.client.login(username=self.user.username, password=PASSWORD)
response = self.client.get(self.url, content_type="application/json")
self.assertEqual(response.status_code, 200)
self.assertEqual(
response.data,
[{
"accepts_logins": True,
"name": "Google",
"disconnect_url": "/auth/disconnect/google-oauth2/?",
"connect_url": "/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings",
"connected": False,
"id": "oa2-google-oauth2"
}]
)

View File

@@ -3,7 +3,7 @@
from django.conf import settings
from django.conf.urls import url
from .views import UserMappingView, UserView, UserViewV2
from .views import ThirdPartyAuthUserStatusView, UserMappingView, UserView, UserViewV2
PROVIDER_PATTERN = r'(?P<provider_id>[\w.+-]+)(?:\:(?P<idp_slug>[\w.+-]+))?'
@@ -20,4 +20,9 @@ urlpatterns = [
UserMappingView.as_view(),
name='third_party_auth_user_mapping_api',
),
url(
r'^v0/providers/user_status$',
ThirdPartyAuthUserStatusView.as_view(),
name='third_party_auth_user_status_api',
),
]

View File

@@ -8,8 +8,10 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.db.models import Q
from django.http import Http404
from django.urls import reverse
from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication
from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser
from rest_framework import exceptions, status, throttling
from rest_framework import exceptions, permissions, status, throttling
from rest_framework.generics import ListAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
@@ -389,3 +391,53 @@ class UserMappingView(ListAPIView):
context['provider'] = self.provider
return context
class ThirdPartyAuthUserStatusView(APIView):
"""
Provides an API endpoint for retrieving the linked status of the authenticated
user with respect to the third party auth providers configured in the system.
"""
authentication_classes = (
JwtAuthentication, OAuth2AuthenticationAllowInactiveUser, SessionAuthenticationAllowInactiveUser
)
permission_classes = (permissions.IsAuthenticated,)
def get(self, request):
"""
GET /api/third_party_auth/v0/providers/user_status/
**GET Response Values**
{
"accepts_logins": true,
"name": "Google",
"disconnect_url": "/auth/disconnect/google-oauth2/?",
"connect_url": "/auth/login/google-oauth2/?auth_entry=account_settings&next=%2Faccount%2Fsettings",
"connected": false,
"id": "oa2-google-oauth2"
}
"""
tpa_states = []
for state in pipeline.get_provider_user_states(request.user):
# We only want to include providers if they are either currently available to be logged
# in with, or if the user is already authenticated with them.
if state.provider.display_for_login or state.has_account:
tpa_states.append({
'id': state.provider.provider_id,
'name': state.provider.name, # The name of the provider e.g. Facebook
'connected': state.has_account, # Whether the user's edX account is connected with the provider.
# If the user is not connected, they should be directed to this page to authenticate
# with the particular provider, as long as the provider supports initiating a login.
'connect_url': pipeline.get_login_url(
state.provider.provider_id,
pipeline.AUTH_ENTRY_ACCOUNT_SETTINGS,
# The url the user should be directed to after the auth process has completed.
redirect_url=reverse('account_settings'),
),
'accepts_logins': state.provider.accepts_logins,
# If the user is connected, sending a POST request to this url removes the connection
# information for this provider from their edX account.
'disconnect_url': pipeline.get_disconnect_url(state.provider.provider_id, state.association_id),
})
return Response(tpa_states)