Skip to content
Permalink
Browse files
Relax api regex for some models allowng . in names
Default api urls do not allow '.' characters when matching the names,
presumably to ensure '.<format>' specifications are definitely matched
properly. This patch relaxes this as we are definitely going to want to
allow for '.' for things like version names.

 - change the lookup_value_regex for Component, Milestone and Version
   models
 - add hypothesis tests for testing the values that the api is allowed
   to use for names when creating objects from each list view
  • Loading branch information
Gary Martin committed Sep 14, 2021
1 parent 22b632f commit 4228632ce8c124e2bec1f76d83e1252ab5af064a
Showing 6 changed files with 91 additions and 11 deletions.
@@ -17,6 +17,8 @@ psycopg2-binary = { version = "^2.9", optional = true }

[tool.poetry.dev-dependencies]
selenium = "^3.141.0"
django-extensions = "^3.1.3"
hypothesis = "^6.21.0"

[tool.poetry.extras]
postgres = ["psycopg2"]
@@ -3,8 +3,6 @@
from rest_framework import serializers
from rest_framework.reverse import reverse
from ..models import Component, Milestone, Product, Ticket, Version
from rest_framework_nested.serializers import NestedHyperlinkedModelSerializer
from rest_framework_nested.relations import NestedHyperlinkedIdentityField
from functools import partial


@@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.

from django.contrib.auth.models import User
from django.urls import reverse
from rest_framework.test import APITestCase
from rest_framework import status
@@ -27,12 +26,7 @@
Ticket,
Version,
)
from ..serializers import (
ComponentSerializer,
MilestoneSerializer,
TicketSerializer,
VersionSerializer,
)


class TicketApiTest(APITestCase):
"""Tests for ticket API"""
@@ -313,7 +307,7 @@ def test_delete_component(self):


class MilestoneApiTest(APITestCase):
"""Tests for component API"""
"""Tests for milestone API"""

def setUp(self):
self.product = Product.objects.create(prefix="BH", name="Bloodhound")
@@ -0,0 +1,84 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.

from django.urls import reverse
from hypothesis import example, given, strategies as st
from hypothesis.extra.django import TestCase
from rest_framework.test import APIClient, APIRequestFactory
from rest_framework import status

from ...models import Product

name_st = st.text(
st.characters(
blacklist_characters="/",
max_codepoint=1000,
blacklist_categories=("Cc", "Cs")
),
min_size=1
).map(lambda x: x.strip()).filter(lambda s: len(s) > 0)


class CommonAPIPropertiesTestCase(TestCase):
"""Common tests for API"""

def setUp(self):
self.client = APIClient()
self.factory = APIRequestFactory()
self.product = Product.objects.create(prefix="BH", name="Bloodhound")
self.list_uri = reverse(
self.list_view_name,
kwargs={"product_prefix": "BH"}
)


class NameTestsMixin:
@given(name=name_st)
@example("next 1.x")
def test_create(self, name):
data = {
"name": name,
"description": "Example Description",
}

response = self.client.post(self.list_uri, data)

self.assertEqual(response.status_code, status.HTTP_201_CREATED)


class ComponentAPIPropertiesTest(CommonAPIPropertiesTestCase, NameTestsMixin):
"""Hypothesis tests for component API"""

def setUp(self):
self.list_view_name = "product-components-list"
super().setUp()


class MilestoneAPIPropertiesTest(CommonAPIPropertiesTestCase, NameTestsMixin):
"""Hypothesis tests for milestone API"""

def setUp(self):
self.list_view_name = "product-milestones-list"
super().setUp()


class VersionAPIPropertiesTest(CommonAPIPropertiesTestCase, NameTestsMixin):
"""Hypothesis tests for version API"""

def setUp(self):
self.list_view_name = "product-versions-list"
super().setUp()
@@ -18,7 +18,6 @@
from django.urls import path
from django.conf.urls import include
from rest_framework.schemas import get_schema_view
from rest_framework.renderers import JSONOpenAPIRenderer
from rest_framework_nested import routers
from . import views

@@ -63,6 +63,7 @@ class ComponentViewSet(viewsets.ModelViewSet):
queryset = models.Component.objects.all()
serializer_class = serializers.ComponentSerializer
lookup_field = 'name'
lookup_value_regex = '[^/]+'

def get_queryset(self, *args, **kwargs):
prefix = self.kwargs['product_prefix']
@@ -73,6 +74,7 @@ class MilestoneViewSet(viewsets.ModelViewSet):
queryset = models.Milestone.objects.all()
serializer_class = serializers.MilestoneSerializer
lookup_field = 'name'
lookup_value_regex = '[^/]+'

def get_queryset(self, *args, **kwargs):
prefix = self.kwargs['product_prefix']
@@ -83,6 +85,7 @@ class VersionViewSet(viewsets.ModelViewSet):
queryset = models.Version.objects.all()
serializer_class = serializers.VersionSerializer
lookup_field = 'name'
lookup_value_regex = '[^/]+'

def get_queryset(self, *args, **kwargs):
prefix = self.kwargs['product_prefix']

0 comments on commit 4228632

Please sign in to comment.