Skip to content

Commit

Permalink
task: backend tests for user permissions (#279)
Browse files Browse the repository at this point in the history
* chore: adds tests for user permissions

* removes extra space
  • Loading branch information
emi-hi authored Apr 22, 2024
1 parent f4910f3 commit 61368a1
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 3 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ The Clean Transportation Data Hub provides an evidence base for the Clean Transp
- This is where you can make changes to your package.json
- You can technically make changes to your packages without going into your container, but you'll need npm installed into your system


- To run in testing mode
if you don't have docker-compose-local-dev.yml locally, create a new file and
add the contents from docker-compose plus a line for:
- KEYCLOAK_TESTING=True
in api environment

to run using this docker file:
docker-compose -f docker-compose-local-dev.yml up

this ensures that the authentication skips the actual keycloak authentication
and uses the user table to get permissions

# Rebasing Guide
- To rebase your branch onto the latest release branch:
- ```git fetch upstream```
Expand Down
10 changes: 8 additions & 2 deletions django/api/keycloak_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@

from django.conf import settings
from rest_framework import authentication, exceptions
from api.models.user import User


class KeycloakAuthentication(authentication.BaseAuthentication):
def authenticate(self, request):
auth = request.headers.get("Authorization", None)

if settings.KEYCLOAK_TESTING:
try:
user = User.objects.get(idir=auth['idir'])
return user.idir, None
except User.DoesNotExist as exc:
# print("Testing User does not exist")
raise User.DoesNotExist(str(exc))
if not auth:
raise exceptions.AuthenticationFailed("Authorization token required")

try:
scheme, token = auth.split()
except ValueError:
Expand Down
2 changes: 1 addition & 1 deletion django/api/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@
KEYCLOAK_CLIENT_ID = os.getenv("KEYCLOAK_CLIENT_ID")
KEYCLOAK_REALM = os.getenv("KEYCLOAK_REALM")
KEYCLOAK_URL = os.getenv("KEYCLOAK_URL", "http://localhost:8080")

KEYCLOAK_TESTING = os.getenv("KEYCLOAK_TESTING", False)

MINIO_ACCESS_KEY = os.getenv("MINIO_ROOT_USER")
MINIO_SECRET_KEY = os.getenv("MINIO_ROOT_PASSWORD")
Expand Down
89 changes: 89 additions & 0 deletions django/api/tests/test_user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
from unittest.mock import MagicMock
from django.test import TestCase
from api.keycloak_authentication import KeycloakAuthentication
from rest_framework.test import APIRequestFactory
from rest_framework.response import Response
from rest_framework import status
from django.http import HttpResponse
from rest_framework import exceptions

from api.models.permission import Permission
from api.models.user import User
from api.models.user_permission import UserPermission
from api.viewsets.user import UserViewSet
from api.viewsets.upload import UploadViewset
from api.decorators.permission import check_upload_permission
class TestUsers(TestCase):
def setUp(self):
self.factory = APIRequestFactory()
self.userauth = KeycloakAuthentication()
self.view = UserViewSet.as_view({'get': 'list'})
#user with no permission
self.test_user = User.objects.create(idir='test_user')

#user with admin permission
self.test_admin_permission = Permission.objects.create(description='admin')
self.test_admin_user = User.objects.create(idir='test_admin_user')
self.admin_user_permission = UserPermission.objects.create(user=self.test_admin_user, permission=self.test_admin_permission)

#user with upload permission
self.test_upload_permission = Permission.objects.create(description='uploader')
self.test_upload_user = User.objects.create(idir='test_upload_user')
self.upload_user_permission = UserPermission.objects.create(user=self.test_upload_user, permission=self.test_upload_permission)


def test_get_user_list(self):
self.assertTrue(User.objects.filter(idir='test_user').exists())
request = self.factory.get('/api/users/list')
request.META = {
'HTTP_AUTHORIZATION': {
'idir': 'test_user'
}
}
response = self.view(request)
self.assertEqual(response.status_code, 403) # Forbidden status code

self.assertTrue(User.objects.filter(idir='test_upload_user').exists())
request_uploader = self.factory.get('/api/users/list')
request_uploader.META = {
'HTTP_AUTHORIZATION': {
'idir': 'test_upload_user'
}
}
response = self.view(request_uploader)
self.assertEqual(response.status_code, 403) # Forbidden status code

self.assertTrue(User.objects.filter(idir='test_admin_user').exists())
request_admin = self.factory.get('/api/users/list')
request_admin.META = {
'HTTP_AUTHORIZATION': {
'idir': 'test_admin_user'
}
}
response = self.view(request_admin)
self.assertEqual(response.status_code, 200) # OK status code
def test_not_authenticated_user(self):
request = self.factory.get('/api/users/list')
request.META = {
'HTTP_AUTHORIZATION': {
'idir': 'test'
}
}
with self.assertRaises(User.DoesNotExist):
_user, _auth = self.userauth.authenticate(request)

def test_upload_user_permissions(self):
# test decorator for user with upload permission
@check_upload_permission()
def mock_import_function(request):
return HttpResponse()
request = self.factory.post('/api/users/list')
request.user = 'test_upload_user'
response = mock_import_function(request)
self.assertEqual(response.status_code, 200) # OK status code

request_admin = self.factory.post('/api/users/list')
request_admin.user = 'test_admin_user'
response = mock_import_function(request_admin)
self.assertEqual(response.status_code, 403) # Forbidden!

0 comments on commit 61368a1

Please sign in to comment.