Skip to content

Commit

Permalink
refactor view and middleware into actually working (#1999)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikkonie committed Oct 9, 2024
1 parent 98af57a commit 167ee6b
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 29 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Changed
- Use constants for timeline event status types (#2010)
- **Irodsbackend**
- Rename ``LocalAuthAPIView`` to ``BasicAuthView`` (#1999)
- Change ``BasicAuthView`` request to ``GET`` (#1999)
- **Irodsinfo**
- Update REST API versioning (#1936)
- **Landingzones**
Expand Down
2 changes: 1 addition & 1 deletion docs_manual/source/sodar_release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Release for SODAR Core v1.0 upgrade, iRODS v4.3 upgrade and feature updates.
- Add Python v3.11 support
- Add study plugin override via ISA-Tab comments
- Add session control in Django settings and environment variables
- Add token-based iRODS basic auth support for OIDC users
- Add token-based iRODS/IGV basic auth support for OIDC users
- Update minimum supported iRODS version to v4.3.3
- Update REST API versioning
- Update REST API views for OpenAPI support
Expand Down
14 changes: 7 additions & 7 deletions irodsbackend/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,54 +38,54 @@ def setUp(self):

def test_post(self):
"""Test TestBasicAuthView POST with existing local user"""
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header(LOCAL_USER_NAME, LOCAL_USER_PASS)
)
self.assertEqual(response.status_code, 200)

@override_settings(IRODS_SODAR_AUTH=False)
def test_post_disabled(self):
"""Test POST with local and auth check disabled"""
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header(LOCAL_USER_NAME, LOCAL_USER_PASS)
)
self.assertEqual(response.status_code, 500)

def test_post_invalid_user(self):
"""Test POST with invalid user"""
response = self.client.post(
response = self.client.get(
self.url,
**self._get_auth_header(LOCAL_USER_NAME, 'invalid_password')
)
self.assertEqual(response.status_code, 401)

def test_post_invalid_password(self):
"""Test POST with invalid password"""
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header('invalid_user', LOCAL_USER_PASS)
)
self.assertEqual(response.status_code, 401)

def test_post_token(self):
"""Test POST with knox token"""
knox_token = self.get_token(self.user)
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header(LOCAL_USER_NAME, knox_token)
)
self.assertEqual(response.status_code, 200)

def test_post_token_invalid(self):
"""Test POST with invalid knox token (should fail)"""
self.get_token(self.user) # Making sure the user has A token
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header(LOCAL_USER_NAME, EMPTY_KNOX_TOKEN)
)
self.assertEqual(response.status_code, 401)

def test_post_token_invalid_username(self):
"""Test POST with username not matching token (should fail)"""
knox_token = self.get_token(self.user)
response = self.client.post(
response = self.client.get(
self.url, **self._get_auth_header('invalid_user', knox_token)
)
self.assertEqual(response.status_code, 401)
2 changes: 1 addition & 1 deletion irodsbackend/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
# NOTE: Not exactly REST API view, but URL maintained for backwards comp
path(
route='api/auth',
view=views.BasicAuthAPIView.as_view(),
view=views.BasicAuthView.as_view(),
name='api_auth',
),
]
30 changes: 14 additions & 16 deletions irodsbackend/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import logging

from django.conf import settings
from django.http import JsonResponse
from django.http import HttpResponse, JsonResponse
from django.views.generic import View

from rest_framework.response import Response
from rest_framework.views import APIView

from sodar.users.auth import fallback_to_auth_basic

Expand Down Expand Up @@ -229,39 +230,36 @@ def get(self, request, *args, **kwargs):
# Basic Auth View --------------------------------------------------------------


# NOTE: Must be based on APIView to avoid CSRF token check
@fallback_to_auth_basic
class BasicAuthAPIView(APIView):
class BasicAuthView(View):
"""
REST API view for verifying login credentials for local users in iRODS.
View for verifying login credentials for local users in iRODS.
Should only be used in local development and testing situations or when an
external LDAP/AD login is not available.
"""

http_method_names = ['post']
http_method_names = ['get']

def post(self, request, *args, **kwargs):
# TODO: Fix so that we actually get here with a token request
def dispatch(self, request, *args, **kwargs):
if not settings.IRODS_SODAR_AUTH:
logger.error(
'{} failed: {}'.format(
BASIC_AUTH_LOG_PREFIX, BASIC_AUTH_NOT_ENABLED_MSG
)
)
return JsonResponse(
{'detail': BASIC_AUTH_NOT_ENABLED_MSG}, status=500
)
return HttpResponse(BASIC_AUTH_NOT_ENABLED_MSG, status=500)
return super().dispatch(request, *args, **kwargs)

def get(self, request, *args, **kwargs):
if request.user.is_authenticated:
logger.info(
'{} successful: {}'.format(
BASIC_AUTH_LOG_PREFIX, request.user.username
)
)
return JsonResponse({'detail': 'Authenticated'}, status=200)
return HttpResponse('Authenticated', status=200)
logger.error(
'{} failed: User {} not authenticated'.format(
BASIC_AUTH_LOG_PREFIX, request.user.username
)
'{} failed: User not authenticated'.format(BASIC_AUTH_LOG_PREFIX)
)
return JsonResponse({'detail': 'Unauthorized'}, status=401)
return HttpResponse('Unauthorized', status=401)
10 changes: 6 additions & 4 deletions sodar/users/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
class FallbackToAuthBasicMiddleware(MiddlewareMixin):
"""
Authentication middleware that allows users to use HTTP Auth Basic instead
of requiring the user to be in the session.
of requiring the user to be in the session. Allows using of a Knox token in
place of password.
"""

def process_request(self, request):
Expand All @@ -44,6 +45,7 @@ def process_request(self, request):
user = authenticate(username=uname, password=passwd)
if user:
login(request, user)
return
# If not authenticated, try token
token_auth = TokenAuthentication()
try:
Expand All @@ -53,9 +55,9 @@ def process_request(self, request):
except Exception:
return
if user and user.is_authenticated and user.username == uname:
# TODO: How to log in user with token here?
# TODO: Currently we return response here skipping view method..
return HttpResponse(status=200)
user.backend = 'django.contrib.auth.backends.ModelBackend'
login(request, user)
return

def process_response(self, request, response):
if not request.user.is_authenticated:
Expand Down

0 comments on commit 167ee6b

Please sign in to comment.