Commit 3d92ea03 authored by Joern jkuensem's avatar Joern jkuensem

TMSS-138: Restrict access to Cycle view via REST calls, add tests to...

TMSS-138: Restrict access to Cycle view via REST calls, add tests to demonstrate use of groups and permissions
parent ca72b119
......@@ -82,7 +82,7 @@ SECRET_KEY = '-&$!kx$_0)u1x#zk9w^^81hfssaover2(8wdq_8n8n3u(8=-9n' # todo:
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['localhost']
# Application definition
......@@ -183,7 +183,8 @@ REST_FRAMEWORK = {
#'rest_framework.permissions.AllowAny',
#'rest_framework.permissions.IsAdminUser',
'rest_framework.permissions.IsAuthenticated',
#'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
#'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
#'rest_framework.permissions.DjangoModelPermissions'
],
'PAGE_SIZE': 50,
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
......@@ -234,8 +235,8 @@ OIDC_DRF_AUTH_BACKEND = 'mozilla_django_oidc.auth.OIDCAuthenticationBackend'
# For talking to Mozilla Identity Provider:
OIDC_RP_SCOPES = "openid email groups"
OIDC_RP_CLIENT_ID = os.environ.get('OIDC_RP_CLIENT_ID', '1') # Secret, do not put real credentials on Git
OIDC_RP_SCOPES = "openid email profile" # todo: groups are not a standard scope, how to handle those?
OIDC_RP_CLIENT_ID = os.environ.get('OIDC_RP_CLIENT_ID', '2') # Secret, do not put real credentials on Git
OIDC_RP_CLIENT_SECRET = os.environ.get('OIDC_RP_CLIENT_SECRET', 'secret') # Secret, do not put real credentials on Git
OIDC_ENDPOINT_HOST = os.environ.get('OIDC_ENDPOINT_HOST', 'tmss_test_oidc')
OIDC_OP_AUTHORIZATION_ENDPOINT="http://%s:8088/openid/authorize" % OIDC_ENDPOINT_HOST
......
# Generated by Django 2.0.6 on 2020-01-23 10:57
# Generated by Django 2.0.6 on 2020-02-04 11:17
import django.contrib.postgres.fields
import django.contrib.postgres.fields.jsonb
......
......@@ -6,7 +6,7 @@ from ..populate import *
class Migration(migrations.Migration):
dependencies = [
('tmssapp', '0002_auto_20200123_1057'),
('tmssapp', '0002_auto_20200204_1117'),
]
operations = [ migrations.RunPython(populate_choices) ]
......@@ -7,6 +7,8 @@ from rest_framework import viewsets
from .lofar_viewset import LOFARViewSet
from .. import models, serializers
from rest_framework.renderers import BrowsableAPIRenderer, TemplateHTMLRenderer
from rest_framework.decorators import permission_classes
from rest_framework.permissions import IsAuthenticatedOrReadOnly, DjangoModelPermissions
class TagsViewSet(LOFARViewSet):
queryset = models.Tags.objects.all()
......@@ -78,6 +80,7 @@ class TaskConnectorsViewSet(LOFARViewSet):
serializer_class = serializers.TaskConnectorsSerializer
@permission_classes((DjangoModelPermissions,)) # example override of default permissions per viewset | todo: review for production
class CycleViewSet(LOFARViewSet):
queryset = models.Cycle.objects.all()
serializer_class = serializers.CycleSerializer
......
......@@ -26,9 +26,11 @@ endif()
lofar_add_test(t_tmssapp_specification_django)
lofar_add_test(t_tmssapp_specification_functional)
lofar_add_test(t_tmssapp_specification_permissions)
lofar_add_test(t_tmssapp_scheduling_django)
lofar_add_test(t_tmssapp_scheduling_functional)
# copy helper script to bin dir
configure_file(test_funcs.sh ${CMAKE_CURRENT_BINARY_DIR}/test_funcs.sh COPYONLY)
......
#!/usr/bin/env python3
# Copyright (C) 2018 ASTRON (Netherlands Institute for Radio Astronomy)
# P.O. Box 2, 7990 AA Dwingeloo, The Netherlands
#
# This file is part of the LOFAR software suite.
# The LOFAR software suite is free software: you can redistribute it and/or
# modify it under the terms of the GNU General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# The LOFAR software suite is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with the LOFAR software suite. If not, see <http://www.gnu.org/licenses/>.
# $Id: $
import unittest
import rest_framework.test
from tmss.tmssapp.populate import populate_choices
from tmss.tmssapp import models
from django.db.utils import IntegrityError
from django.contrib.auth.models import User, Group, Permission, ContentType
from test_utils import assertDataWithUrls, assertUrlList
import uuid
import json
from datetime import datetime
# use this to create timezone-aware datetime objects: from django.utils import timezone
client = rest_framework.test.APIClient()
BASE_URI = '/api'
class CycleTest(rest_framework.test.APITransactionTestCase):
reset_sequences = True
def setUp(self):
self.user, _ = User.objects.get_or_create(username='paulus', email='paulus@boskabouter.com')
self.support_group, _ = Group.objects.get_or_create(name='support')
self.support_group.permissions.add(Permission.objects.get(codename='add_cycle'))
# for user-specific permission use e.g.:
# self.user.user_permissions.add(Permission.objects.get(codename='add_cycle'))
self.admin_group, _ = Group.objects.get_or_create(name='admin')
self.admin_group.permissions.add(Permission.objects.get(codename='delete_cycle'))
client.force_login(self.user)
# test data # todo: Jorrit created some factory methods for this, I think, so we should use that after a merge
self.test_data_1 = {"name": 'my_cycle' + str(uuid.uuid4()),
"description": "",
"tags": [],
"start": datetime.utcnow().isoformat(),
"stop": datetime.utcnow().isoformat(),
"number": 1,
"standard_hours": 2,
"expert_hours": 3,
"filler_hours": 4}
# test data
self.test_data_2 = {"name": 'my_cycle' + str(uuid.uuid4()),
"description": "This is my other cycle",
"tags": ['othercycle'],
"start": datetime.utcnow().isoformat(),
"stop": datetime.utcnow().isoformat(),
"number": 4,
"standard_hours": 3,
"expert_hours": 2,
"filler_hours": 1}
def tearDown(self):
client.logout()
def test_Cycle_cannot_be_added_without_group(self):
self.user.groups.set([])
self.assertFalse(self.user.has_perm('tmssapp.add_cycle'))
res = client.post('%s/cycle/' % BASE_URI, data=self.test_data_1)
self.assertEqual(res.status_code, 403)
def test_Cycle_can_be_added_by_support(self):
self.user.groups.set([self.support_group])
self.assertTrue(self.user.has_perm('tmssapp.add_cycle'))
res = client.post('%s/cycle/' % BASE_URI, data=self.test_data_2)
self.assertEqual(res.status_code, 201)
#self.assertEqual(0, len(models.Cycle.objects.all()))
#models.Cycle.objects.create(**self.test_data_1)
#self.assertEqual(7, len(models.Cycle.objects.all()))
#self.user.groups.set([self.support_group])
#self.user.save()
#self.assertTrue(self.user.has_perm('tmssapp.change_cycle'))
#models.Cycle.objects.create(**self.test_data_1)
def test_Cycle_can_only_be_deleted_by_admin(self):
self.user.groups.set([self.admin_group])
# add
count = len(models.Cycle.objects.all())
models.Cycle.objects.create(**self.test_data_2)
url = '%s/cycle/%s/' % (BASE_URI, self.test_data_2['name'])
self.assertEqual(count+1, len(models.Cycle.objects.all()))
# delete
res = client.delete(url)
self.assertEqual(res.status_code, 204)
new_count = len(models.Cycle.objects.all())
self.assertEqual(count, len(models.Cycle.objects.all()))
\ No newline at end of file
#!/bin/bash
. test_funcs.sh
setup
run_test "$LOFARROOT/lib*/python*/site-packages/lofar/sas/tmss/manage.py test --pattern=t_tmssapp_specification_permissions.py --testrunner=postgres_testrunner.PostgresqlTestRunner"
#!/bin/sh
./runctest.sh t_tmssapp_specification_permissions
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment