Skip to content

Commit e1e7a5b

Browse files
authored
Merge branch 'main' into add-almalinux-advisories
2 parents 444b66a + dcb0511 commit e1e7a5b

File tree

119 files changed

+23633
-377
lines changed

Some content is hidden

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

119 files changed

+23633
-377
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

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ ACTIVATE?=. ${VENV}/bin/activate;
2929
VIRTUALENV_PYZ=etc/thirdparty/virtualenv.pyz
3030
# Do not depend on Python to generate the SECRET_KEY
3131
GET_SECRET_KEY=`base64 /dev/urandom | head -c50`
32+
GET_ALTCHA_HMAC_KEY=`head -c 32 /dev/urandom | xxd -p -c 32`
3233
# Customize with `$ make envfile ENV_FILE=/etc/vulnerablecode/.env`
3334
ENV_FILE=.env
3435
# Customize with `$ make postgres VULNERABLECODE_DB_PASSWORD=YOUR_PASSWORD`
@@ -63,6 +64,7 @@ envfile:
6364
@if test -f ${ENV_FILE}; then echo ".env file exists already"; exit 1; fi
6465
@mkdir -p $(shell dirname ${ENV_FILE}) && touch ${ENV_FILE}
6566
@echo SECRET_KEY=\"${GET_SECRET_KEY}\" > ${ENV_FILE}
67+
@echo ALTCHA_HMAC_KEY=\"${GET_ALTCHA_HMAC_KEY}\" >> ${ENV_FILE}
6668

6769
isort:
6870
@echo "-> Apply isort changes to ensure proper imports ordering"

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: 3 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
@@ -100,8 +101,7 @@ install_requires =
100101
#vulntotal
101102
python-dotenv
102103
texttable
103-
104-
django-recaptcha>=4.0.0
104+
extractcode[full]==31.0.0
105105

106106

107107
[options.extras_require]

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)