Skip to content

Commit e4d508e

Browse files
committed
Merge latest main branch
Signed-off-by: Philippe Ombredanne <[email protected]>
1 parent fe1e9bb commit e4d508e

File tree

7 files changed

+53
-23
lines changed

7 files changed

+53
-23
lines changed

vulnerabilities/api.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from vulnerabilities.models import VulnerabilityReference
2424
from vulnerabilities.models import VulnerabilitySeverity
2525
from vulnerabilities.models import get_purl_query_lookups
26+
from vulnerabilities.throttling import StaffUserRateThrottle
2627

2728

2829
class VulnerabilitySeveritySerializer(serializers.ModelSerializer):
@@ -228,9 +229,11 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
228229
serializer_class = PackageSerializer
229230
filter_backends = (filters.DjangoFilterBackend,)
230231
filterset_class = PackageFilterSet
232+
throttle_classes = [StaffUserRateThrottle]
233+
throttle_scope = "packages"
231234

232235
# TODO: Fix the swagger documentation for this endpoint
233-
@action(detail=False, methods=["post"])
236+
@action(detail=False, methods=["post"], throttle_scope="bulk_search_packages")
234237
def bulk_search(self, request):
235238
"""
236239
Lookup for vulnerable packages using many Package URLs at once.
@@ -254,15 +257,15 @@ def bulk_search(self, request):
254257
if purl_data:
255258
purl_response = PackageSerializer(purl_data[0], context={"request": request}).data
256259
else:
257-
purl_response = purl
260+
purl_response = purl.to_dict()
258261
purl_response["unresolved_vulnerabilities"] = []
259262
purl_response["resolved_vulnerabilities"] = []
260263
purl_response["purl"] = purl_string
261264
response.append(purl_response)
262265

263266
return Response(response)
264267

265-
@action(detail=False, methods=["get"])
268+
@action(detail=False, methods=["get"], throttle_scope="vulnerable_packages")
266269
def all(self, request):
267270
"""
268271
Return the Package URLs of all packages known to be vulnerable.
@@ -314,6 +317,8 @@ def get_queryset(self):
314317
serializer_class = VulnerabilitySerializer
315318
filter_backends = (filters.DjangoFilterBackend,)
316319
filterset_class = VulnerabilityFilterSet
320+
throttle_classes = [StaffUserRateThrottle]
321+
throttle_scope = "vulnerabilities"
317322

318323

319324
class CPEFilterSet(filters.FilterSet):
@@ -334,9 +339,11 @@ class CPEViewSet(viewsets.ReadOnlyModelViewSet):
334339
).distinct()
335340
serializer_class = VulnerabilitySerializer
336341
filter_backends = (filters.DjangoFilterBackend,)
342+
throttle_classes = [StaffUserRateThrottle]
337343
filterset_class = CPEFilterSet
344+
throttle_scope = "cpes"
338345

339-
@action(detail=False, methods=["post"])
346+
@action(detail=False, methods=["post"], throttle_scope="bulk_search_cpes")
340347
def bulk_search(self, request):
341348
"""
342349
Lookup for vulnerabilities using many CPEs at once.
@@ -378,3 +385,5 @@ class AliasViewSet(viewsets.ReadOnlyModelViewSet):
378385
serializer_class = VulnerabilitySerializer
379386
filter_backends = (filters.DjangoFilterBackend,)
380387
filterset_class = AliasFilterSet
388+
throttle_classes = [StaffUserRateThrottle]
389+
throttle_scope = "aliases"

vulnerabilities/forms.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,24 @@ class ApiUserCreationForm(forms.ModelForm):
4141
class Meta:
4242
model = ApiUser
4343
fields = (
44-
"username",
44+
"email",
4545
"first_name",
4646
"last_name",
4747
)
4848

4949
def __init__(self, *args, **kwargs):
5050
super(ApiUserCreationForm, self).__init__(*args, **kwargs)
51-
self.fields["username"].help_text = f"<ul><li>{self.fields['username'].help_text}</li></ul>"
51+
self.fields["email"].required = True
5252

5353
def save(self, commit=True):
5454
return ApiUser.objects.create_api_user(
55-
username=self.cleaned_data["username"],
55+
username=self.cleaned_data["email"],
5656
first_name=self.cleaned_data["first_name"],
5757
last_name=self.cleaned_data["last_name"],
5858
)
5959

6060
def clean_username(self):
61-
username = self.cleaned_data["username"]
61+
username = self.cleaned_data["email"]
6262
validate_email(username)
6363
return username
6464

vulnerabilities/models.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import logging
1313
from contextlib import suppress
1414

15-
from django.conf import settings
1615
from django.contrib.auth import get_user_model
1716
from django.contrib.auth.models import UserManager
1817
from django.core import exceptions
@@ -24,7 +23,6 @@
2423
from django.db.models import Q
2524
from django.db.models.functions import Length
2625
from django.db.models.functions import Trim
27-
from django.dispatch import receiver
2826
from django.urls import reverse
2927
from packageurl import PackageURL
3028
from packageurl.contrib.django.models import PackageURLMixin

vulnerabilities/templates/api_user_creation_form.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
{% block content %}
66
<section class="section pt-0">
7+
{% for message in messages %}
8+
<article class="message is-{% if message.level_tag == 'error' %}danger{% else %}{{ message.level_tag }}{% endif %}">
9+
<div class="message-body">
10+
{{ message|linebreaksbr }}
11+
</div>
12+
</article>
13+
{% endfor %}
714
{% block title %}
815
VulnerableCode API key request
916
{% endblock %}

vulnerabilities/tests/test_auth.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424

2525
class VulnerableCodeAuthTest(TestCase):
2626
def setUp(self):
27-
self.basic_user = ApiUser.objects.create_api_user(
28-
username="[email protected]", password=TEST_PASSWORD
29-
)
27+
self.basic_user = ApiUser.objects.create_api_user(username="[email protected]")
3028

3129
def test_vulnerablecode_auth_api_required_authentication(self):
3230
response = self.client.get(api_package_url)

vulnerabilities/views.py

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
# See https://aboutcode.org for more information about nexB OSS projects.
88
#
99

10+
from django.contrib import messages
11+
from django.core.exceptions import ValidationError
1012
from django.core.mail import send_mail
11-
from django.http import HttpResponse
1213
from django.http.response import Http404
14+
from django.shortcuts import redirect
1315
from django.shortcuts import render
1416
from django.urls import reverse_lazy
1517
from django.views import View
@@ -40,6 +42,11 @@ def get_context_data(self, **kwargs):
4042
return context
4143

4244
def get_queryset(self, query=None):
45+
"""
46+
Return a Package queryset for the ``query``.
47+
Make a best effort approach to find matching packages either based
48+
on exact purl, partial purl or just name and namespace.
49+
"""
4350
query = query or self.request.GET.get("search") or ""
4451
return self.model.objects.search(query).with_vulnerability_counts().prefetch_related()
4552

@@ -140,18 +147,26 @@ class ApiUserCreateView(generic.CreateView):
140147
template_name = "api_user_creation_form.html"
141148

142149
def form_valid(self, form):
143-
super().form_valid(form)
150+
151+
try:
152+
response = super().form_valid(form)
153+
except ValidationError:
154+
messages.error(self.request, "Email is invalid or already taken")
155+
return redirect(self.get_success_url())
144156

145157
send_mail(
146158
subject="VulnerableCode.io API key token",
147159
message=f"Here is your VulnerableCode.io API key token: {self.object.auth_token}",
148160
from_email=env.str("FROM_EMAIL", default=""),
149161
recipient_list=[self.object.email],
162+
fail_silently=True,
150163
)
151164

152-
return HttpResponse(
153-
f"Check your email for VulnerableCode.io API key token: {self.object.email}"
165+
messages.success(
166+
self.request, f"API key token sent to your email address {self.object.email}."
154167
)
155168

169+
return response
170+
156171
def get_success_url(self):
157-
return reverse_lazy("home")
172+
return reverse_lazy("api_user_request")

vulnerablecode/settings.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@
6565
"vulnerabilities",
6666
# Django built-in
6767
"django.contrib.auth",
68-
"django.contrib.admin",
6968
"django.contrib.contenttypes",
7069
"django.contrib.sessions",
7170
"django.contrib.messages",
7271
"django.contrib.staticfiles",
72+
"django.contrib.admin",
7373
"django.contrib.humanize",
7474
# Third-party apps
7575
"django_filters",
@@ -161,10 +161,6 @@
161161

162162
USE_I18N = True
163163

164-
USE_L10N = True
165-
166-
USE_TZ = True
167-
168164
IS_TESTS = False
169165

170166
if len(sys.argv) > 0:
@@ -200,6 +196,10 @@
200196
}
201197

202198

199+
USE_L10N = True
200+
201+
USE_TZ = True
202+
203203
# Static files (CSS, JavaScript, Images)
204204

205205
STATIC_URL = "/static/"
@@ -210,6 +210,7 @@
210210
str(PROJECT_DIR / "static"),
211211
]
212212

213+
213214
CRISPY_TEMPLATE_PACK = "bootstrap4"
214215

215216
# Third-party apps
@@ -293,9 +294,11 @@
293294
"TAGS_SORTER": False,
294295
}
295296

297+
296298
if not VULNERABLECODEIO_REQUIRE_AUTHENTICATION:
297299
REST_FRAMEWORK["DEFAULT_PERMISSION_CLASSES"] = ("rest_framework.permissions.AllowAny",)
298300

301+
299302
if DEBUG_TOOLBAR:
300303
INSTALLED_APPS += ("debug_toolbar",)
301304

0 commit comments

Comments
 (0)