Skip to content

Commit f690ad7

Browse files
committed
Merge remote-tracking branch 'origin/main' into 1903-gitlab-importer-package-first
2 parents fb49371 + da873aa commit f690ad7

File tree

87 files changed

+11499
-345
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+11499
-345
lines changed

CHANGELOG.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
Release notes
22
=============
33

4+
Version v37.0.0
5+
---------------------
6+
7+
- This is a major version, this version introduces Advisory level details
8+
https://github.com/aboutcode-org/vulnerablecode/issues/1796
9+
https://github.com/aboutcode-org/vulnerablecode/issues/1393
10+
https://github.com/aboutcode-org/vulnerablecode/issues/1883
11+
https://github.com/aboutcode-org/vulnerablecode/issues/1882
12+
https://github.com/aboutcode-org/vulnerablecode/pull/1866
13+
- We have added new models AdvisoryV2, AdvisoryAlias, AdvisoryReference, AdvisorySeverity, AdvisoryWeakness, PackageV2 and CodeFixV2.
14+
- We are using ``avid`` as an internal advisory ID for uniquely identifying advisories.
15+
- We have a new route ``/v2`` which only support package search which has information on packages that are reported to be affected or fixing by advisories.
16+
- This version introduces ``/api/v2/advisories-packages`` which has information on packages that are reported to be affected or fixing by advisories.
17+
- Pipeline Dashboard improvements #1920.
18+
- Throttle API requests based on user permissions #1909.
19+
- Add pipeline to compute Advisory ToDos #1764
20+
421
Version v36.1.3
522
---------------------
623

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ decorator==5.1.1
2828
defusedxml==0.7.1
2929
distro==1.7.0
3030
Django==4.2.22
31+
django-altcha==0.2.0
3132
django-crispy-forms==2.3
3233
django-environ==0.11.2
3334
django-filter==24.3
34-
django-recaptcha==4.0.0
3535
django-widget-tweaks==1.5.0
3636
djangorestframework==3.15.2
3737
doc8==0.11.1

setup.cfg

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = vulnerablecode
3-
version = 36.1.3
3+
version = 37.0.0
44
license = Apache-2.0 AND CC-BY-SA-4.0
55

66
# description must be on ONE line https://github.com/pypa/setuptools/issues/1390
@@ -65,6 +65,7 @@ install_requires =
6565
crispy-bootstrap4>=2024.1
6666
django-environ>=0.11.0
6767
gunicorn>=23.0.0
68+
django-altcha==0.2.0
6869

6970
# for the API doc
7071
drf-spectacular[sidecar]>=0.24.2
@@ -101,8 +102,6 @@ install_requires =
101102
python-dotenv
102103
texttable
103104

104-
django-recaptcha>=4.0.0
105-
106105

107106
[options.extras_require]
108107
dev =

vulnerabilities/admin.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99

1010
from django import forms
1111
from django.contrib import admin
12+
from django.contrib.admin.widgets import FilteredSelectMultiple
13+
from django.contrib.auth.admin import GroupAdmin as BasicGroupAdmin
14+
from django.contrib.auth.models import Group
15+
from django.contrib.auth.models import User
1216
from django.core.validators import validate_email
1317

1418
from vulnerabilities.models import ApiUser
@@ -17,6 +21,10 @@
1721
from vulnerabilities.models import VulnerabilityReference
1822
from vulnerabilities.models import VulnerabilitySeverity
1923

24+
admin.site.site_header = "VulnerableCode Administration"
25+
admin.site.site_title = "VulnerableCode Admin Portal"
26+
admin.site.index_title = "Welcome to VulnerableCode Management"
27+
2028

2129
@admin.register(Vulnerability)
2230
class VulnerabilityAdmin(admin.ModelAdmin):
@@ -97,3 +105,50 @@ def get_form(self, request, obj=None, **kwargs):
97105
defaults["form"] = self.add_form
98106
defaults.update(kwargs)
99107
return super().get_form(request, obj, **defaults)
108+
109+
110+
class GroupWithUsersForm(forms.ModelForm):
111+
users = forms.ModelMultipleChoiceField(
112+
queryset=User.objects.all(),
113+
required=False,
114+
widget=FilteredSelectMultiple("Users", is_stacked=False),
115+
label="Users",
116+
)
117+
118+
class Meta:
119+
model = Group
120+
fields = "__all__"
121+
122+
def __init__(self, *args, **kwargs):
123+
super().__init__(*args, **kwargs)
124+
self.fields["users"].label_from_instance = lambda user: (
125+
f"{user.username} | {user.email}" if user.email else user.username
126+
)
127+
if self.instance.pk:
128+
self.fields["users"].initial = self.instance.user_set.all()
129+
130+
def save(self, commit=True):
131+
group = super().save(commit=commit)
132+
group.save()
133+
self.save_m2m()
134+
group.user_set.set(self.cleaned_data["users"])
135+
return group
136+
137+
138+
admin.site.unregister(Group)
139+
140+
141+
@admin.register(Group)
142+
class GroupAdmin(admin.ModelAdmin):
143+
form = GroupWithUsersForm
144+
search_fields = ("name",)
145+
ordering = ("name",)
146+
filter_horizontal = ("permissions",)
147+
148+
def formfield_for_manytomany(self, db_field, request=None, **kwargs):
149+
if db_field.name == "permissions":
150+
qs = kwargs.get("queryset", db_field.remote_field.model.objects)
151+
# Avoid a major performance hit resolving permission names which
152+
# triggers a content_type load:
153+
kwargs["queryset"] = qs.select_related("content_type")
154+
return super().formfield_for_manytomany(db_field, request=request, **kwargs)

vulnerabilities/api.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from rest_framework import viewsets
2323
from rest_framework.decorators import action
2424
from rest_framework.response import Response
25-
from rest_framework.throttling import AnonRateThrottle
2625

2726
from vulnerabilities.models import Alias
2827
from vulnerabilities.models import Exploit
@@ -34,7 +33,7 @@
3433
from vulnerabilities.models import get_purl_query_lookups
3534
from vulnerabilities.severity_systems import EPSS
3635
from vulnerabilities.severity_systems import SCORING_SYSTEMS
37-
from vulnerabilities.throttling import StaffUserRateThrottle
36+
from vulnerabilities.throttling import PermissionBasedUserRateThrottle
3837
from vulnerabilities.utils import get_severity_range
3938

4039

@@ -471,7 +470,7 @@ class PackageViewSet(viewsets.ReadOnlyModelViewSet):
471470
serializer_class = PackageSerializer
472471
filter_backends = (filters.DjangoFilterBackend,)
473472
filterset_class = PackageFilterSet
474-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
473+
throttle_classes = [PermissionBasedUserRateThrottle]
475474

476475
def get_queryset(self):
477476
return super().get_queryset().with_is_vulnerable()
@@ -688,7 +687,7 @@ def get_queryset(self):
688687
serializer_class = VulnerabilitySerializer
689688
filter_backends = (filters.DjangoFilterBackend,)
690689
filterset_class = VulnerabilityFilterSet
691-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
690+
throttle_classes = [PermissionBasedUserRateThrottle]
692691

693692

694693
class CPEFilterSet(filters.FilterSet):

vulnerabilities/api_extension.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from rest_framework.serializers import ModelSerializer
2424
from rest_framework.serializers import Serializer
2525
from rest_framework.serializers import ValidationError
26-
from rest_framework.throttling import AnonRateThrottle
2726

2827
from vulnerabilities.api import BaseResourceSerializer
2928
from vulnerabilities.models import Exploit
@@ -33,7 +32,7 @@
3332
from vulnerabilities.models import VulnerabilitySeverity
3433
from vulnerabilities.models import Weakness
3534
from vulnerabilities.models import get_purl_query_lookups
36-
from vulnerabilities.throttling import StaffUserRateThrottle
35+
from vulnerabilities.throttling import PermissionBasedUserRateThrottle
3736

3837

3938
class SerializerExcludeFieldsMixin:
@@ -259,7 +258,7 @@ class V2PackageViewSet(viewsets.ReadOnlyModelViewSet):
259258
lookup_field = "purl"
260259
filter_backends = (filters.DjangoFilterBackend,)
261260
filterset_class = V2PackageFilterSet
262-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
261+
throttle_classes = [PermissionBasedUserRateThrottle]
263262

264263
def get_queryset(self):
265264
return super().get_queryset().with_is_vulnerable().prefetch_related("vulnerabilities")
@@ -345,7 +344,7 @@ class VulnerabilityViewSet(viewsets.ReadOnlyModelViewSet):
345344
lookup_field = "vulnerability_id"
346345
filter_backends = (filters.DjangoFilterBackend,)
347346
filterset_class = V2VulnerabilityFilterSet
348-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
347+
throttle_classes = [PermissionBasedUserRateThrottle]
349348

350349
def get_queryset(self):
351350
"""
@@ -381,7 +380,7 @@ class CPEViewSet(viewsets.ReadOnlyModelViewSet):
381380
).distinct()
382381
serializer_class = V2VulnerabilitySerializer
383382
filter_backends = (filters.DjangoFilterBackend,)
384-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
383+
throttle_classes = [PermissionBasedUserRateThrottle]
385384
filterset_class = CPEFilterSet
386385

387386
@action(detail=False, methods=["post"])
@@ -420,4 +419,4 @@ class AliasViewSet(viewsets.ReadOnlyModelViewSet):
420419
serializer_class = V2VulnerabilitySerializer
421420
filter_backends = (filters.DjangoFilterBackend,)
422421
filterset_class = AliasFilterSet
423-
throttle_classes = [StaffUserRateThrottle, AnonRateThrottle]
422+
throttle_classes = [PermissionBasedUserRateThrottle]

0 commit comments

Comments
 (0)