Skip to content

Commit 469bfbb

Browse files
authored
Add anonymous questionnaire to engagement (#10734)
* add-anonymous-questionnaire-to-engagement initial scaffolding for new feature * add-anonymous-questionnaire-to-engagement Add templats and form, update to actually perform linking * add-anonymous-questionnaire-to-engagement wording change on form * add-anonymous-questionnaire-to-engagement comments, wording change * add-anonymous-questionnaire-to-engagement redirect to engagement view rather than edit after linking * add-anonymous-questionnaire-to-engagement Allow relinking (reassociating) of questionnaires to another engagement. add link to contextual menu on engagement q listing * add-anonymous-questionnaire-to-engagement linter fixes * add-anonymous-questionnaire-to-engagement formatting * add-anonymous-questionnaire-to-engagement fix typo
1 parent e8551aa commit 469bfbb

File tree

6 files changed

+95
-0
lines changed

6 files changed

+95
-0
lines changed

dojo/forms.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import dojo.jira_link.helper as jira_helper
3232
from dojo.authorization.roles_permissions import Permissions
3333
from dojo.endpoint.utils import endpoint_filter, endpoint_get_or_create, validate_endpoints_to_add
34+
from dojo.engagement.queries import get_authorized_engagements
3435
from dojo.finding.queries import get_authorized_findings
3536
from dojo.group.queries import get_authorized_groups, get_group_member_roles
3637
from dojo.models import (
@@ -3550,6 +3551,18 @@ def __init__(self, *args, **kwargs):
35503551
self.fields["product"].queryset = get_authorized_products(Permissions.Engagement_Add)
35513552

35523553

3554+
class ExistingEngagementForm(forms.Form):
3555+
engagement = forms.ModelChoiceField(
3556+
queryset=Engagement.objects.none(),
3557+
required=True,
3558+
widget=forms.widgets.Select(),
3559+
help_text="Select which Engagement to link the Questionnaire to")
3560+
3561+
def __init__(self, *args, **kwargs):
3562+
super().__init__(*args, **kwargs)
3563+
self.fields["engagement"].queryset = get_authorized_engagements(Permissions.Engagement_Edit).order_by("-target_start")
3564+
3565+
35533566
class ConfigurationPermissionsForm(forms.Form):
35543567

35553568
def __init__(self, *args, **kwargs):

dojo/survey/urls.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,7 @@
7777
re_path(r"^empty_questionnaire/(?P<esid>\d+)/new_engagement$",
7878
views.engagement_empty_survey,
7979
name="engagement_empty_survey"),
80+
re_path(r"^empty_questionnaire/(?P<esid>\d+)/existing_engagement$",
81+
views.ExistingEngagementEmptySurveyView.as_view(),
82+
name="existing_engagement_empty_survey"),
8083
]

dojo/survey/views.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from django.urls import reverse
1212
from django.utils import timezone as tz
1313
from django.utils.html import escape
14+
from django.views import View
1415

1516
from dojo.authorization.authorization import (
1617
user_has_configuration_permission,
@@ -36,6 +37,7 @@
3637
EditChoiceQuestionForm,
3738
EditQuestionnaireQuestionsForm,
3839
EditTextQuestionForm,
40+
ExistingEngagementForm,
3941
)
4042
from dojo.models import (
4143
Answer,
@@ -866,3 +868,57 @@ def engagement_empty_survey(request, esid):
866868
top_level=False,
867869
request=request)
868870
return render(request, "defectDojo-engagement-survey/add_engagement.html", {"form": form})
871+
872+
873+
class ExistingEngagementEmptySurveyView(View):
874+
def get(self, request, esid):
875+
survey = get_object_or_404(Answered_Survey, id=esid)
876+
if survey.engagement:
877+
# If the questionnaire is already linked to a survey, ensure the user has permission to edit it
878+
user_has_permission_or_403(request.user, survey.engagement, Permissions.Engagement_Edit)
879+
# Prepopulate the form with the current engagement
880+
form = self.get_form_class()({"engagement": survey.engagement})
881+
else:
882+
form = self.get_form_class()()
883+
self.add_breadcrumb(request)
884+
return render(request, self.get_template(), {"form": form})
885+
886+
def post(self, request, esid):
887+
survey = get_object_or_404(Answered_Survey, id=esid)
888+
form = self.get_form_class()(request.POST)
889+
if form.is_valid():
890+
# Validate perms on the target engagement
891+
engagement = form.cleaned_data.get("engagement")
892+
user_has_permission_or_403(request.user, engagement, Permissions.Engagement_Edit)
893+
# If we're moving a questionnaire, make sure the user can edit the 'source' engagement too
894+
if survey.engagement:
895+
user_has_permission_or_403(request.user, survey.engagement, Permissions.Engagement_Edit)
896+
# Link and save
897+
survey.engagement = engagement
898+
survey.save()
899+
messages.add_message(
900+
request,
901+
messages.SUCCESS,
902+
"Questionnaire successfully linked to Engagement.",
903+
extra_tags="alert-success")
904+
return HttpResponseRedirect(reverse("view_engagement", args=(engagement.id,)))
905+
906+
messages.add_message(
907+
request,
908+
messages.ERROR,
909+
"Questionnaire could not be linked to the selected Engagement.",
910+
extra_tags="alert-danger")
911+
self.add_breadcrumb(request)
912+
return render(request, self.get_template(), {"form": form})
913+
914+
def add_breadcrumb(self, request):
915+
add_breadcrumb(
916+
title="Link Questionnaire to existing Engagement",
917+
top_level=False,
918+
request=request)
919+
920+
def get_form_class(self):
921+
return ExistingEngagementForm
922+
923+
def get_template(self):
924+
return "defectDojo-engagement-survey/existing_engagement.html"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{% extends "base.html" %}
2+
{% block content %}
3+
{{ block.super }}
4+
<h3>Link Questionnaire to Existing Engagement</h3>
5+
<br />
6+
<form class="form-horizontal" method="post">
7+
{% csrf_token %}
8+
{% include "dojo/form_fields.html" with form=form %}
9+
<div class="form-group">
10+
<div class="col-sm-offset-2 col-sm-10">
11+
<input class="btn btn-primary" type="submit" label="existing_engagement" name="existing_engagement" value="Link to Engagement"/>
12+
</div>
13+
</div>
14+
</form>
15+
{% endblock %}

dojo/templates/defectDojo-engagement-survey/surveys.html

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@
4040
<i class="fa-solid fa-plus"></i> Assign User</a>
4141
</li>
4242
{% endif %}
43+
{% if survey.engagement|has_object_permission:"Engagement_Edit" %}
44+
<li role="presentation">
45+
<a class="" href="/empty_questionnaire/{{ survey.id }}/existing_engagement">
46+
<i class="fa-solid fa-link"></i> Link to a Different Engagement
47+
</a>
48+
</li>
49+
{% endif %}
4350
<li>
4451
<a class="" data-toggle="modal"
4552
data-target="#shareQuestionnaireModal"

dojo/templates/dojo/dashboard.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
<a class="btn btn-sm btn-secondary"
209209
href="/empty_questionnaire/{{ survey.id }}">{% trans "View Responses" %}</a>
210210
<a class="btn btn-sm btn-success" href="/empty_questionnaire/{{ survey.id }}/new_engagement">{% trans "Create Engagement" %}</a>
211+
<a class="btn btn-sm btn-success" href="/empty_questionnaire/{{ survey.id }}/existing_engagement">{% trans "Link to Existing Engagement" %}</a>
211212
<button class="btn btn-sm btn-info" disabled
212213
href="/engagement/{{ survey.engagement.id }}/questionnaire/{{ survey.id }}/assign">{% trans "Assign User" %}</button>
213214
{% endif %}

0 commit comments

Comments
 (0)