Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
Signed-off-by: Tushar Goel <tushar.goel.dav@gmail.com>
  • Loading branch information
TG1999 committed Aug 17, 2022
1 parent c1e9d2b commit f662e41
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 43 deletions.
13 changes: 4 additions & 9 deletions vulnerabilities/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
from vulnerabilities.models import Vulnerability
from vulnerabilities.models import VulnerabilityReference
from vulnerabilities.models import VulnerabilitySeverity
from vulnerablecode.auth import ConditionalLoginRequired


class VulnerabilitySeveritySerializer(serializers.ModelSerializer):
Expand All @@ -31,10 +30,6 @@ class Meta:
fields = ["value", "scoring_system"]


class AuthenticatedAPIViewSet(ConditionalLoginRequired, viewsets.ReadOnlyModelViewSet):
pass


class VulnerabilityReferenceSerializer(serializers.ModelSerializer):
scores = VulnerabilitySeveritySerializer(many=True, source="vulnerabilityseverity_set")
reference_url = serializers.CharField(source="url")
Expand Down Expand Up @@ -211,7 +206,7 @@ def filter_purl(self, queryset, name, value):
return self.queryset.filter(**attrs)


class PackageViewSet(AuthenticatedAPIViewSet):
class PackageViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Package.objects.all()
serializer_class = PackageSerializer
filter_backends = (filters.DjangoFilterBackend,)
Expand Down Expand Up @@ -258,7 +253,7 @@ class Meta:
fields = ["vulnerability_id"]


class VulnerabilityViewSet(AuthenticatedAPIViewSet):
class VulnerabilityViewSet(viewsets.ReadOnlyModelViewSet):
def get_fixed_packages_qs(self):
"""
Filter the packages that fixes a vulnerability
Expand Down Expand Up @@ -300,7 +295,7 @@ def filter_cpe(self, queryset, name, value):
return self.queryset.filter(vulnerabilityreference__reference_id__startswith=cpe).distinct()


class CPEViewSet(AuthenticatedAPIViewSet):
class CPEViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Vulnerability.objects.filter(
vulnerabilityreference__reference_id__startswith="cpe"
).distinct()
Expand Down Expand Up @@ -341,7 +336,7 @@ def filter_alias(self, queryset, name, value):
return self.queryset.filter(aliases__alias__icontains=alias)


class AliasViewSet(AuthenticatedAPIViewSet):
class AliasViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Vulnerability.objects.all()
serializer_class = VulnerabilitySerializer
filter_backends = (filters.DjangoFilterBackend,)
Expand Down
3 changes: 1 addition & 2 deletions vulnerabilities/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,4 @@
</footer>
</body>
{% block javascript %}
{% endblock %}
</html>
{% endblock %}
90 changes: 90 additions & 0 deletions vulnerabilities/tests/test_auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#
# Copyright (c) nexB Inc. and others. All rights reserved.
# VulnerableCode is a trademark of nexB Inc.
# SPDX-License-Identifier: Apache-2.0
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
# See https://github.com/nexB/vulnerablecode for support or download.
# See https://aboutcode.org for more information about nexB OSS projects.
# This is copied from https://github.com/nexB/scancode.io/commit/eab8eeb13989c26a1600cc64e8b054f171341063
#

from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import AnonymousUser
from django.test import TestCase
from django.test import override_settings
from django.urls import reverse

from vulnerablecode.auth import is_authenticated_when_required

TEST_PASSWORD = "secret"

User = get_user_model()

login_url = reverse("login")
logout_url = reverse("logout")
profile_url = reverse("account_profile")
api_package_url = "/api/packages/"
login_redirect_url = settings.LOGIN_REDIRECT_URL


class VulnerableCodeAuthTest(TestCase):
def setUp(self):
self.anonymous_user = AnonymousUser()
self.basic_user = User.objects.create_user(username="basic_user", password=TEST_PASSWORD)

def test_vulnerablecode_auth_is_authenticated_when_required(self):
self.assertFalse(self.anonymous_user.is_authenticated)
self.assertFalse(is_authenticated_when_required(user=self.anonymous_user))

self.assertTrue(self.basic_user.is_authenticated)
self.assertTrue(is_authenticated_when_required(user=self.basic_user))

with override_settings(VULNERABLECODEIO_REQUIRE_AUTHENTICATION=False):
self.assertTrue(is_authenticated_when_required(user=None))

def test_vulnerablecode_auth_login_view(self):
data = {"username": self.basic_user.username, "password": ""}
response = self.client.post(login_url, data)
form = response.context_data["form"]
expected_error = {"password": ["This field is required."]}
self.assertEqual(expected_error, form.errors)

data = {"username": self.basic_user.username, "password": "wrong"}
response = self.client.post(login_url, data)
form = response.context_data["form"]
expected_error = {
"__all__": [
"Please enter a correct username and password. "
"Note that both fields may be case-sensitive."
]
}
self.assertEqual(expected_error, form.errors)

data = {"username": self.basic_user.username, "password": TEST_PASSWORD}
response = self.client.post(login_url, data, follow=True)
self.assertRedirects(response, login_redirect_url)
expected = '<a class="navbar-link">basic_user</a>'
self.assertContains(response, expected, html=True)

def test_vulnerablecode_auth_logout_view(self):
response = self.client.get(logout_url)
self.assertRedirects(response, login_url)

self.client.login(username=self.basic_user.username, password=TEST_PASSWORD)
response = self.client.get(logout_url)
self.assertRedirects(response, login_url)

def test_vulnerablecode_account_profile_view(self):
self.client.login(username=self.basic_user.username, password=TEST_PASSWORD)
response = self.client.get(profile_url)
expected = '<label class="label">API Key</label>'
self.assertContains(response, expected, html=True)
expected = '<label class="label">API Key</label>'
self.assertContains(response, self.basic_user.auth_token.key)

def test_vulnerablecode_auth_api_required_authentication(self):
response = self.client.get(api_package_url)
expected = {"detail": "Authentication credentials were not provided."}
self.assertEqual(expected, response.json())
self.assertEqual(401, response.status_code)
89 changes: 59 additions & 30 deletions vulnerabilities/tests/test_fix_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
# See https://aboutcode.org for more information about nexB OSS projects.
#

import json

from django.contrib.auth import get_user_model
from django.test import TestCase
from django.test import TransactionTestCase
from django.utils.http import int_to_base36
from packageurl import PackageURL
from rest_framework import status
from rest_framework.test import APIClient

from vulnerabilities.models import Alias
from vulnerabilities.models import Package
Expand All @@ -19,9 +24,15 @@
from vulnerabilities.models import VulnerabilityReference
from vulnerabilities.models import VulnerabilityRelatedReference

User = get_user_model()


class APITestCaseVulnerability(TestCase):
class APITestCaseVulnerability(TransactionTestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
for i in range(0, 200):
Vulnerability.objects.create(
summary=str(i),
Expand All @@ -35,15 +46,15 @@ def setUp(self):
)

def test_api_status(self):
response = self.client.get("/api/vulnerabilities/", format="json")
response = self.csrf_client.get("/api/vulnerabilities/")
self.assertEqual(status.HTTP_200_OK, response.status_code)

def test_api_response(self):
response = self.client.get("/api/vulnerabilities/", format="json").data
response = self.csrf_client.get("/api/vulnerabilities/").data
self.assertEqual(response["count"], 201)

def test_api_with_single_vulnerability(self):
response = self.client.get(
response = self.csrf_client.get(
f"/api/vulnerabilities/{self.vulnerability.id}", format="json"
).data
assert response == {
Expand All @@ -66,7 +77,7 @@ def test_api_with_single_vulnerability(self):
}

def test_api_with_single_vulnerability_with_filters(self):
response = self.client.get(
response = self.csrf_client.get(
f"/api/vulnerabilities/{self.vulnerability.id}?type=pypi", format="json"
).data
assert response == {
Expand All @@ -87,6 +98,10 @@ def test_api_with_single_vulnerability_with_filters(self):

class APITestCasePackage(TestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
vuln = Vulnerability.objects.create(
summary="test-vuln",
)
Expand Down Expand Up @@ -123,15 +138,15 @@ def setUp(self):
)

def test_api_status(self):
response = self.client.get("/api/packages/", format="json")
response = self.csrf_client.get("/api/packages/", format="json")
self.assertEqual(status.HTTP_200_OK, response.status_code)

def test_api_response(self):
response = self.client.get("/api/packages/", format="json").data
response = self.csrf_client.get("/api/packages/", format="json").data
self.assertEqual(response["count"], 11)

def test_api_with_single_vulnerability_and_fixed_package(self):
response = self.client.get(f"/api/packages/{self.package.id}", format="json").data
response = self.csrf_client.get(f"/api/packages/{self.package.id}", format="json").data
assert response == {
"url": f"http://testserver/api/packages/{self.package.id}",
"purl": "pkg:generic/nginx/test@11",
Expand Down Expand Up @@ -160,7 +175,7 @@ def test_api_with_single_vulnerability_and_fixed_package(self):
}

def test_api_with_single_vulnerability_and_vulnerable_package(self):
response = self.client.get(f"/api/packages/{self.vuln_package.id}", format="json").data
response = self.csrf_client.get(f"/api/packages/{self.vuln_package.id}", format="json").data
assert response == {
"url": f"http://testserver/api/packages/{self.vuln_package.id}",
"purl": "pkg:generic/nginx/test@9",
Expand Down Expand Up @@ -204,6 +219,10 @@ def test_api_with_single_vulnerability_and_vulnerable_package(self):

class CPEApi(TestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
self.vulnerability = Vulnerability.objects.create(summary="test")
for i in range(0, 10):
ref, _ = VulnerabilityReference.objects.get_or_create(
Expand All @@ -214,31 +233,39 @@ def setUp(self):
)

def test_api_status(self):
response = self.client.get("/api/cpes/", format="json")
response = self.csrf_client.get("/api/cpes/", format="json")
self.assertEqual(status.HTTP_200_OK, response.status_code)

def test_api_response(self):
response = self.client.get("/api/cpes/?cpe=cpe:/a:nginx:9", format="json").data
response = self.csrf_client.get("/api/cpes/?cpe=cpe:/a:nginx:9", format="json").data
self.assertEqual(response["count"], 1)


class AliasApi(TestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
self.vulnerability = Vulnerability.objects.create(summary="test")
for i in range(0, 10):
Alias.objects.create(alias=f"CVE-{i}", vulnerability=self.vulnerability)

def test_api_status(self):
response = self.client.get("/api/alias/", format="json")
response = self.csrf_client.get("/api/alias/", format="json")
self.assertEqual(status.HTTP_200_OK, response.status_code)

def test_api_response(self):
response = self.client.get("/api/alias?alias=CVE-9", format="json").data
response = self.csrf_client.get("/api/alias?alias=CVE-9", format="json").data
self.assertEqual(response["count"], 1)


class BulkSearchAPI(TestCase):
class BulkSearchAPIPackage(TestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
packages = [
"pkg:nginx/nginx@0.6.18",
"pkg:nginx/nginx@1.20.0",
Expand All @@ -264,16 +291,20 @@ def test_api_response(self):
request_body = {
"purls": self.packages,
}
response = self.client.post(
response = self.csrf_client.post(
"/api/packages/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert len(response) == 13


class BulkSearchAPI(TestCase):
class BulkSearchAPICPE(TestCase):
def setUp(self):
self.user = User.objects.create_user("username", "e@mail.com", "secret")
self.auth = f"Token {self.user.auth_token.key}"
self.csrf_client = APIClient(enforce_csrf_checks=True)
self.csrf_client.credentials(HTTP_AUTHORIZATION=self.auth)
self.exclusive_cpes = [
"cpe:/a:nginx:1.0.7",
"cpe:/a:nginx:1.0.15",
Expand Down Expand Up @@ -305,9 +336,9 @@ def test_api_response_with_with_exclusive_cpes_associated_with_two_vulnerabiliti
request_body = {
"cpes": self.exclusive_cpes,
}
response = self.client.post(
response = self.csrf_client.post(
"/api/cpes/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert len(response) == 1
Expand All @@ -320,9 +351,9 @@ def test_api_response_with_no_cpe_associated(self):
request_body = {
"cpes": ["cpe:/a:nginx:1.10.7"],
}
response = self.client.post(
response = self.csrf_client.post(
"/api/cpes/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert len(response) == 0
Expand All @@ -331,9 +362,9 @@ def test_api_response_with_with_non_exclusive_cpes_associated_with_two_vulnerabi
request_body = {
"cpes": self.non_exclusive_cpes,
}
response = self.client.post(
response = self.csrf_client.post(
"/api/cpes/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert len(response) == 2
Expand All @@ -342,20 +373,18 @@ def test_with_empty_list(self):
request_body = {
"cpes": [],
}
response = self.client.post(
response = self.csrf_client.post(
"/api/cpes/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert response == {"Error": "A non-empty 'cpe' list of package URLs is required."}

def test_with_invalid_cpes(self):
request_body = {
"cpes": ["CVE-2022-2022"],
}
response = self.client.post(
request_body = {"cpes": ["CVE-2022-2022"]}
response = self.csrf_client.post(
"/api/cpes/bulk_search",
data=request_body,
data=json.dumps(request_body),
content_type="application/json",
).json()
assert response == {"Error": "Invalid CPE: CVE-2022-2022"}
Loading

0 comments on commit f662e41

Please sign in to comment.