[Patchew-devel] [PATCH 3/3] Add Infra for PUT
Shubham Jain
shubhamjain7495 at gmail.com
Wed Aug 8 11:12:26 UTC 2018
Added authentications and validation of the data for PUT of the result
---
api/rest.py | 47 +++++++++++++++++++++++++++++++++++++++++++----
tests/test_git.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++
tests/test_testing.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 137 insertions(+), 4 deletions(-)
diff --git a/api/rest.py b/api/rest.py
index 21f4609..dd3a947 100644
--- a/api/rest.py
+++ b/api/rest.py
@@ -26,6 +26,9 @@ import rest_framework
from mbox import addr_db_to_rest, MboxMessage
from rest_framework.parsers import JSONParser, BaseParser
from rest_framework.authentication import SessionAuthentication
+from rest_framework.exceptions import ValidationError
+import re
+import mod
class CsrfExemptSessionAuthentication(SessionAuthentication):
@@ -65,8 +68,9 @@ class PatchewPermission(permissions.BasePermission):
def has_generic_permission(self, request, view):
return (request.method in permissions.SAFE_METHODS) or \
- self.is_superuser(request) or \
- self.has_group_permission(request, view)
+ self.is_superuser(request) or \
+ self.has_group_permission(request, view) or \
+ self.has_result_group_permission(request, view)
def has_permission(self, request, view):
return self.has_generic_permission(request, view) or \
@@ -78,7 +82,22 @@ class PatchewPermission(permissions.BasePermission):
(isinstance(obj, Message) and \
self.has_message_permission(request, view, obj)) or \
(isinstance(obj, Project) and \
- self.has_project_permission(request, view, obj))
+ self.has_project_permission(request, view, obj)) or \
+ (isinstance(obj, Result) and \
+ self.has_result_permission(request, view, obj))
+
+ def has_result_group_permission(self, request, view):
+ name = request.resolver_match.kwargs.get('name')
+ if name:
+ found = re.match("^[^.]*", name)
+ module = mod.get_module(found.group(0)) if found else None
+ for grp in request.user.groups.all():
+ if grp.name in module.allowed_groups:
+ return True
+ return False
+
+ def has_result_permission(self, request, view, result_obj):
+ return self.has_object_permission(request, view, result_obj.project)
class ImportPermission(PatchewPermission):
allowed_groups = ('importers',)
@@ -475,6 +494,14 @@ class ResultSerializer(serializers.ModelSerializer):
request = self.context['request']
return obj.get_log_url(request)
+ def validate(self, data):
+ found = re.match("^[^.]*", self.instance.name)
+ module = mod.get_module(found.group(0)) if found else None
+ is_valid = module.result_data_serializer_class(data=data['data']).is_valid(raise_exception=True)
+ if found is None and not is_valid:
+ raise ValidationError("Invalid")
+ return data
+
class ResultSerializerFull(ResultSerializer):
class Meta:
model = Result
@@ -484,18 +511,30 @@ class ResultSerializerFull(ResultSerializer):
log = CharField(required=False)
class ResultsViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin,
- viewsets.GenericViewSet):
+ mixins.UpdateModelMixin, viewsets.GenericViewSet):
lookup_field = 'name'
lookup_value_regex = '[^/]+'
filter_backends = (filters.OrderingFilter,)
ordering_fields = ('name',)
ordering = ('name',)
+ authentication_classes = (CsrfExemptSessionAuthentication, )
+ permission_classes = (PatchewPermission, )
def get_serializer_class(self, *args, **kwargs):
if self.lookup_field in self.kwargs:
return ResultSerializerFull
return ResultSerializer
+ @property
+ def project(self):
+ if hasattr(self, '__project'):
+ return self.__project
+ try:
+ self.__project = Project.objects.get(id=self.kwargs['projects_pk'])
+ except:
+ self.__project = None
+ return self.__project
+
class ProjectResultsViewSet(ResultsViewSet):
def get_queryset(self):
return ProjectResult.objects.filter(project=self.kwargs['projects_pk'])
diff --git a/tests/test_git.py b/tests/test_git.py
index b2802d5..e22a498 100755
--- a/tests/test_git.py
+++ b/tests/test_git.py
@@ -15,6 +15,7 @@ from tests.patchewtest import PatchewTestCase, main
import shutil
import subprocess
from api.models import Message, Result
+import json
class GitTest(PatchewTestCase):
@@ -101,6 +102,52 @@ class GitTest(PatchewTestCase):
self.assertEqual(resp.data['log_url'], None)
self.assertEqual(resp.data['log'], None)
+ def test_auth_importer(self):
+ self.cli_import("0013-foo-patch.mbox.gz")
+ MESSAGE_ID = '20160628014747.20971-1-famz at redhat.com'
+ test = self.create_user(username="test", password="userpass", groups=['importers'])
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name": "testing.a",
+ "status": "failure",
+ "data": {"tag": "test_tag", "url": "test_url", "repo": "test_repo", "base": "test_base"},
+ "log": "test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+
+ resp= self.api_client.put('%sseries/%s/results/git/' % (self.PROJECT_BASE, MESSAGE_ID), data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp.status_code, 200)
+ self.assertEquals(resp.data['log'], "test")
+
+ def test_data_validation(self):
+ self.cli_import("0013-foo-patch.mbox.gz")
+ MESSAGE_ID = '20160628014747.20971-1-famz at redhat.com'
+ test = self.create_user(username="test", password="userpass", groups=['importers'])
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name": "testing.a",
+ "status": "failure",
+ "data": "",
+ "log": "test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+
+ resp= self.api_client.put('%sseries/%s/results/git/' % (self.PROJECT_BASE, MESSAGE_ID), data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp.status_code, 400)
+
+ def test_auth_without_permission(self):
+ self.cli_import("0013-foo-patch.mbox.gz")
+ MESSAGE_ID = '20160628014747.20971-1-famz at redhat.com'
+ test = self.create_user(username="test", password="userpass")
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name": "testing.a",
+ "status": "failure",
+ "data": {"tag": "test_tag", "url": "test_url", "repo": "test_repo", "base": "test_base"},
+ "log": "test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+
+ resp= self.api_client.put('%sseries/%s/results/git/' % (self.PROJECT_BASE, MESSAGE_ID), data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp.status_code, 403)
+
def test_rest_git_base(self):
self.cli_import("0013-foo-patch.mbox.gz")
self.do_apply()
diff --git a/tests/test_testing.py b/tests/test_testing.py
index 7ca4625..85b16a6 100755
--- a/tests/test_testing.py
+++ b/tests/test_testing.py
@@ -15,6 +15,7 @@ import subprocess
sys.path.append(os.path.dirname(__file__))
from tests.patchewtest import PatchewTestCase, main
from api.models import Message, Result
+import json
def create_test(project, name):
prefix = "testing.tests." + name + "."
@@ -214,6 +215,7 @@ class TesterTest(PatchewTestCase):
self.p1 = self.add_project("QEMU", "qemu-devel at nongnu.org")
create_test(self.p1, "a")
+ self.PROJECT_BASE = '%sprojects/%d/' % (self.REST_BASE, self.p1.id)
self.p2 = self.add_project("UMEQ", "qemu-devel at nongnu.org")
create_test(self.p2, "b")
@@ -248,6 +250,51 @@ class TesterTest(PatchewTestCase):
cwd=self.repo).decode()
p.set_property("git.head", head)
+ def test_auth_tester(self):
+ resp = self.api_client.get('%sresults/' % (
+ self.PROJECT_BASE))
+ test = self.create_user(username="test", password="userpass", groups=['testers'])
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name": "testing.a",
+ "status": "failure",
+ "data": {"head": "test_head", "tester": "test_tester", "is_timeout": False},
+ "log": "test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+
+ resp1= self.api_client.put(resp.data['results'][0]['resource_uri'],data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp1.status_code, 200)
+ self.assertEquals(resp1.data['log'], "test")
+
+ def test_data_validation(self):
+ resp = self.api_client.get('%sresults/' % (
+ self.PROJECT_BASE))
+ test = self.create_user(username="test", password="userpass", groups=['testers'])
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name":"testing.a",
+ "status":"failure",
+ "data":"",
+ "log":"test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+ resp1= self.api_client.put(resp.data['results'][0]['resource_uri'],data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp1.status_code, 400)
+
+ def test_auth_without_permission(self):
+ resp = self.api_client.get('%sresults/' % (
+ self.PROJECT_BASE))
+ test = self.create_user(username="test", password="userpass")
+ self.api_client.login(username="test", password="userpass")
+ data = {
+ "name": "testing.a",
+ "status": "failure",
+ "data": {"head": "test_head", "tester": "test_tester", "is_timeout": False},
+ "log": "test",
+ "last_update": '2018-08-07T03:51:13.262213'}
+
+ resp1= self.api_client.put(resp.data['results'][0]['resource_uri'],data=json.dumps(data), content_type='application/json')
+ self.assertEquals(resp1.status_code, 403)
+
def test_tester(self):
self.cli_login()
out, err = self.check_cli(["tester", "-p", "QEMU,UMEQ",
--
2.15.1 (Apple Git-101)
More information about the Patchew-devel
mailing list