Skip to content

Commit 52e9f16

Browse files
authored
Merge pull request #11073 from DefectDojo/release/2.39.1
Release: Merge release into master from: release/2.39.1
2 parents 340cbb2 + 0962bd6 commit 52e9f16

34 files changed

Lines changed: 571 additions & 83 deletions

README.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,14 @@ Core Moderators can help you with pull requests or feedback on dev ideas:
132132
* Cody Maffucci ([@Maffooch](https://github.com/maffooch) | [LinkedIn](https://www.linkedin.com/in/cody-maffucci))
133133

134134
Moderators can help you with pull requests or feedback on dev ideas:
135-
* Damien Carol ([@damiencarol](https://github.com/damiencarol) | [LinkedIn](https://www.linkedin.com/in/damien-carol/))
136-
* Jannik Jürgens ([@alles-klar](https://github.com/alles-klar))
137-
* Dubravko Sever ([@dsever](https://github.com/dsever))
138135
* Charles Neill ([@cneill](https://github.com/cneill) | [@ccneill](https://twitter.com/ccneill))
139136
* Jay Paz ([@jjpaz](https://twitter.com/jjpaz))
140137
* Blake Owens ([@blakeaowens](https://github.com/blakeaowens))
141138

142139
## Hall of Fame
143-
140+
* Jannik Jürgens ([@alles-klar](https://github.com/alles-klar)) - Jannik was a long time contributor and moderator for
141+
DefectDojo and made significant contributions to many areas of the platform. Jannik was instrumental in pioneering
142+
and optimizing deployment methods.
144143
* Valentijn Scholten ([@valentijnscholten](https://github.com/valentijnscholten) |
145144
[Sponsor](https://github.com/sponsors/valentijnscholten) |
146145
[LinkedIn](https://www.linkedin.com/in/valentijn-scholten/)) - Valentijn served as a core moderator for 3 years.

components/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "defectdojo",
3-
"version": "2.39.0",
3+
"version": "2.39.1",
44
"license" : "BSD-3-Clause",
55
"private": true,
66
"dependencies": {

dojo/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
# Django starts so that shared_task will use this app.
55
from .celery import app as celery_app # noqa: F401
66

7-
__version__ = "2.39.0"
7+
__version__ = "2.39.1"
88
__url__ = "https://github.com/DefectDojo/django-DefectDojo"
99
__docs__ = "https://documentation.defectdojo.com"

dojo/api_v2/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ class JiraProjectViewSet(
15171517
"jira_instance",
15181518
"product",
15191519
"engagement",
1520+
"enabled",
15201521
"component",
15211522
"project_key",
15221523
"push_all_issues",
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.0.8 on 2024-10-10 17:07
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('dojo', '0216_alter_jira_project_push_all_issues'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='jira_project',
15+
name='enabled',
16+
field=models.BooleanField(blank=True, default=True, help_text='When disabled, Findings will no longer be pushed to Jira, even if they have already been pushed previously.', verbose_name='Enable Connection With Jira Project'),
17+
),
18+
]

dojo/fixtures/defect_dojo_sample_data.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35210,6 +35210,7 @@
3521035210
"engagement": null,
3521135211
"component": "",
3521235212
"push_all_issues": false,
35213+
"enabled": true,
3521335214
"enable_engagement_epic_mapping": true,
3521435215
"push_notes": false,
3521535216
"product_jira_sla_notification": false,
@@ -35227,6 +35228,7 @@
3522735228
"engagement": null,
3522835229
"component": "",
3522935230
"push_all_issues": true,
35231+
"enabled": true,
3523035232
"enable_engagement_epic_mapping": true,
3523135233
"push_notes": true,
3523235234
"product_jira_sla_notification": false,
@@ -35244,6 +35246,7 @@
3524435246
"engagement": null,
3524535247
"component": "",
3524635248
"push_all_issues": false,
35249+
"enabled": true,
3524735250
"enable_engagement_epic_mapping": false,
3524835251
"push_notes": false,
3524935252
"product_jira_sla_notification": false,

dojo/forms.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2425,7 +2425,7 @@ def clean(self):
24252425
return self.cleaned_data
24262426

24272427

2428-
class JIRAForm(BaseJiraForm):
2428+
class AdvancedJIRAForm(BaseJiraForm):
24292429
issue_template_dir = forms.ChoiceField(required=False,
24302430
choices=JIRA_TEMPLATE_CHOICES,
24312431
help_text="Choose the folder containing the Django templates used to render the JIRA issue description. These are stored in dojo/templates/issue-trackers. Leave empty to use the default jira_full templates.")
@@ -2445,8 +2445,11 @@ class Meta:
24452445
exclude = [""]
24462446

24472447

2448-
class ExpressJIRAForm(BaseJiraForm):
2448+
class JIRAForm(BaseJiraForm):
24492449
issue_key = forms.CharField(required=True, help_text="A valid issue ID is required to gather the necessary information.")
2450+
issue_template_dir = forms.ChoiceField(required=False,
2451+
choices=JIRA_TEMPLATE_CHOICES,
2452+
help_text="Choose the folder containing the Django templates used to render the JIRA issue description. These are stored in dojo/templates/issue-trackers. Leave empty to use the default jira_full templates.")
24502453

24512454
class Meta:
24522455
model = JIRA_Instance
@@ -2856,7 +2859,7 @@ class JIRAProjectForm(forms.ModelForm):
28562859
class Meta:
28572860
model = JIRA_Project
28582861
exclude = ["product", "engagement"]
2859-
fields = ["inherit_from_product", "jira_instance", "project_key", "issue_template_dir", "epic_issue_type_name", "component", "custom_fields", "jira_labels", "default_assignee", "add_vulnerability_id_to_jira_label", "push_all_issues", "enable_engagement_epic_mapping", "push_notes", "product_jira_sla_notification", "risk_acceptance_expiration_notification"]
2862+
fields = ["inherit_from_product", "jira_instance", "project_key", "issue_template_dir", "epic_issue_type_name", "component", "custom_fields", "jira_labels", "default_assignee", "enabled", "add_vulnerability_id_to_jira_label", "push_all_issues", "enable_engagement_epic_mapping", "push_notes", "product_jira_sla_notification", "risk_acceptance_expiration_notification"]
28602863

28612864
def __init__(self, *args, **kwargs):
28622865
from dojo.jira_link import helper as jira_helper
@@ -2894,6 +2897,7 @@ def __init__(self, *args, **kwargs):
28942897
self.fields["custom_fields"].disabled = False
28952898
self.fields["default_assignee"].disabled = False
28962899
self.fields["jira_labels"].disabled = False
2900+
self.fields["enabled"].disabled = False
28972901
self.fields["add_vulnerability_id_to_jira_label"].disabled = False
28982902
self.fields["push_all_issues"].disabled = False
28992903
self.fields["enable_engagement_epic_mapping"].disabled = False
@@ -2918,6 +2922,7 @@ def __init__(self, *args, **kwargs):
29182922
self.initial["custom_fields"] = jira_project_product.custom_fields
29192923
self.initial["default_assignee"] = jira_project_product.default_assignee
29202924
self.initial["jira_labels"] = jira_project_product.jira_labels
2925+
self.initial["enabled"] = jira_project_product.enabled
29212926
self.initial["add_vulnerability_id_to_jira_label"] = jira_project_product.add_vulnerability_id_to_jira_label
29222927
self.initial["push_all_issues"] = jira_project_product.push_all_issues
29232928
self.initial["enable_engagement_epic_mapping"] = jira_project_product.enable_engagement_epic_mapping
@@ -2933,6 +2938,7 @@ def __init__(self, *args, **kwargs):
29332938
self.fields["custom_fields"].disabled = True
29342939
self.fields["default_assignee"].disabled = True
29352940
self.fields["jira_labels"].disabled = True
2941+
self.fields["enabled"].disabled = True
29362942
self.fields["add_vulnerability_id_to_jira_label"].disabled = True
29372943
self.fields["push_all_issues"].disabled = True
29382944
self.fields["enable_engagement_epic_mapping"].disabled = True

dojo/home/views.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def dashboard(request: HttpRequest) -> HttpResponse:
3333

3434
date_range = [today - timedelta(days=6), today] # 7 days (6 days plus today)
3535
finding_count = findings\
36-
.filter(created__date__range=date_range)\
36+
.filter(date__range=date_range)\
3737
.count()
3838
mitigated_count = findings\
3939
.filter(mitigated__date__range=date_range)\

dojo/jira_link/helper.py

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,12 @@ def is_jira_configured_and_enabled(obj):
7171
if not is_jira_enabled():
7272
return False
7373

74-
if get_jira_project(obj) is None:
74+
jira_project = get_jira_project(obj)
75+
if jira_project is None:
7576
logger.debug('JIRA project not found for: "%s" not doing anything', obj)
7677
return False
7778

78-
return True
79+
return jira_project.enabled
7980

8081

8182
def is_push_to_jira(instance, push_to_jira_parameter=None):
@@ -88,6 +89,10 @@ def is_push_to_jira(instance, push_to_jira_parameter=None):
8889
if push_to_jira_parameter is not None:
8990
return push_to_jira_parameter
9091

92+
# Check to see if jira project is disabled to prevent pushing findings
93+
if not jira_project.enabled:
94+
return False
95+
9196
# push_to_jira was not specified, so look at push_all_issues in JIRA_Project
9297
return jira_project.push_all_issues
9398

@@ -96,8 +101,10 @@ def is_push_all_issues(instance):
96101
if not is_jira_configured_and_enabled(instance):
97102
return False
98103

99-
jira_project = get_jira_project(instance)
100-
if jira_project:
104+
if jira_project := get_jira_project(instance):
105+
# Check to see if jira project is disabled to prevent pushing findings
106+
if not jira_project.enabled:
107+
return None
101108
return jira_project.push_all_issues
102109
return None
103110

@@ -108,9 +115,13 @@ def is_push_all_issues(instance):
108115
# returns True/False, error_message, error_code
109116
def can_be_pushed_to_jira(obj, form=None):
110117
# logger.debug('can be pushed to JIRA: %s', finding_or_form)
111-
if not get_jira_project(obj):
118+
jira_project = get_jira_project(obj)
119+
if not jira_project:
112120
return False, f"{to_str_typed(obj)} cannot be pushed to jira as there is no jira project configuration for this product.", "error_no_jira_project"
113121

122+
if not jira_project.enabled:
123+
return False, f"{to_str_typed(obj)} cannot be pushed to jira as the jira project is not enabled.", "error_no_jira_project"
124+
114125
if not hasattr(obj, "has_jira_issue"):
115126
return False, f"{to_str_typed(obj)} cannot be pushed to jira as there is no jira_issue attribute.", "error_no_jira_issue_attribute"
116127

@@ -1389,6 +1400,13 @@ def add_comment(obj, note, force_push=False, **kwargs):
13891400

13901401
def add_simple_jira_comment(jira_instance, jira_issue, comment):
13911402
try:
1403+
jira_project = get_jira_project(jira_issue)
1404+
1405+
# Check to see if jira project is disabled to prevent pushing findings
1406+
if not jira_project.enabled:
1407+
log_jira_generic_alert("JIRA Project is disabled", "Push to JIRA for Epic skipped because JIRA Project is disabled")
1408+
return False
1409+
13921410
jira = get_jira_connection(jira_instance)
13931411

13941412
jira.add_comment(
@@ -1403,9 +1421,13 @@ def add_simple_jira_comment(jira_instance, jira_issue, comment):
14031421
def finding_link_jira(request, finding, new_jira_issue_key):
14041422
logger.debug("linking existing jira issue %s for finding %i", new_jira_issue_key, finding.id)
14051423

1406-
existing_jira_issue = jira_get_issue(get_jira_project(finding), new_jira_issue_key)
1407-
14081424
jira_project = get_jira_project(finding)
1425+
existing_jira_issue = jira_get_issue(jira_project, new_jira_issue_key)
1426+
1427+
# Check to see if jira project is disabled to prevent pushing findings
1428+
if not jira_project.enabled:
1429+
add_error_message_to_response("Push to JIRA for finding skipped because JIRA Project is disabled")
1430+
return False
14091431

14101432
if not existing_jira_issue:
14111433
raise ValueError("JIRA issue not found or cannot be retrieved: " + new_jira_issue_key)
@@ -1433,9 +1455,13 @@ def finding_link_jira(request, finding, new_jira_issue_key):
14331455
def finding_group_link_jira(request, finding_group, new_jira_issue_key):
14341456
logger.debug("linking existing jira issue %s for finding group %i", new_jira_issue_key, finding_group.id)
14351457

1436-
existing_jira_issue = jira_get_issue(get_jira_project(finding_group), new_jira_issue_key)
1437-
14381458
jira_project = get_jira_project(finding_group)
1459+
existing_jira_issue = jira_get_issue(jira_project, new_jira_issue_key)
1460+
1461+
# Check to see if jira project is disabled to prevent pushing findings
1462+
if not jira_project.enabled:
1463+
add_error_message_to_response("Push to JIRA for group skipped because JIRA Project is disabled")
1464+
return False
14391465

14401466
if not existing_jira_issue:
14411467
raise ValueError("JIRA issue not found or cannot be retrieved: " + new_jira_issue_key)

dojo/jira_link/urls.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
re_path(r"^jira/webhook/(?P<secret>[\w-]+)$", views.webhook, name="jira_web_hook_secret"),
99
re_path(r"^jira/webhook/", views.webhook, name="jira_web_hook"),
1010
re_path(r"^jira/add", views.NewJiraView.as_view(), name="add_jira"),
11+
re_path(r"^jira/advanced", views.AdvancedJiraView.as_view(), name="add_jira_advanced"),
1112
re_path(r"^jira/(?P<jid>\d+)/edit$", views.EditJiraView.as_view(), name="edit_jira"),
1213
re_path(r"^jira/(?P<tid>\d+)/delete$", views.DeleteJiraView.as_view(), name="delete_jira"),
1314
re_path(r"^jira$", views.ListJiraView.as_view(), name="jira"),
14-
re_path(r"^jira/express", views.ExpressJiraView.as_view(), name="express_jira")]
15+
]

0 commit comments

Comments
 (0)