Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions dojo/finding/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@
name="choose_finding_template_options"),
re_path(r"^finding/(?P<fid>\d+)/(?P<tid>\d+)/apply_template_to_finding$",
views.apply_template_to_finding, name="apply_template_to_finding"),
re_path(r"^finding/(?P<fid>\d+)/verify$", views.verify_finding,
name="verify_finding"),
re_path(r"^finding/(?P<fid>\d+)/close$", views.close_finding,
name="close_finding"),
re_path(r"^finding/(?P<fid>\d+)/defect_review$",
Expand Down
66 changes: 66 additions & 0 deletions dojo/finding/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -1226,6 +1226,72 @@ def close_finding(request, fid):
)


@user_is_authorized(Finding, Permissions.Finding_Edit, "fid")
def verify_finding(request, fid):
finding = get_object_or_404(Finding, id=fid)

if finding.verified:
messages.add_message(
request,
messages.INFO,
"Finding already verified.",
extra_tags="alert-info",
)
return redirect_to_return_url_or_else(
request,
reverse("view_finding", args=(finding.id,)),
)

form = NoteForm(data=request.POST or None)
form.fields["entry"].required = False
form.fields["entry"].label = _("Comment (optional)")

if request.method == "POST" and form.is_valid():
entry = form.cleaned_data.get("entry", "").strip()
if entry:
note = form.save(commit=False)
note.author = request.user
note.save()
finding.notes.add(note)

now_time = timezone.now()
finding.verified = True
finding.last_reviewed = now_time
finding.last_reviewed_by = request.user
finding.last_status_update = now_time
finding.save(push_to_jira=False)

messages.add_message(
request,
messages.SUCCESS,
"Finding verified.",
extra_tags="alert-success",
)

return redirect_to_return_url_or_else(
request,
reverse("view_finding", args=(finding.id,)),
)

product_tab = Product_Tab(
finding.test.engagement.product,
title="Verify Finding",
tab="findings",
)

return render(
request,
"dojo/verify_finding.html",
{
"finding": finding,
"product_tab": product_tab,
"user": request.user,
"form": form,
"active_tab": "findings",
},
)


@user_is_authorized(Finding, Permissions.Finding_Edit, "fid")
def defect_finding_review(request, fid):
finding = get_object_or_404(Finding, id=fid)
Expand Down
18 changes: 18 additions & 0 deletions dojo/templates/dojo/verify_finding.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "base.html" %}
{% load i18n %}

{% block content %}
{{ block.super }}
<h3>{% trans "Verify Finding" %}</h3>
<h4>{{ finding.title }}</h4>
<p>{% trans "Use this form to mark the finding as verified. Adding a comment is optional." %}</p>
<form class="form-horizontal" action="{% url 'verify_finding' finding.id %}" method="post">
{% csrf_token %}
{% include "dojo/form_fields.html" with form=form %}
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input class="btn btn-primary" type="submit" value="{% trans "Verify Finding" %}" aria-label="{% trans "Verify Finding" %}"/>
</div>
</div>
</form>
{% endblock %}
40 changes: 39 additions & 1 deletion dojo/templates/dojo/view_finding.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,13 @@ <h3 class="pull-left finding-title">
</a>
</li>
{% else %}
{% if not finding.verified %}
<li role="presentation">
<a href="{% url 'verify_finding' finding.id %}">
<i class="fa-solid fa-circle-check"></i> Verify Finding
</a>
</li>
{% endif %}
<li role="presentation">
<a href="{% url 'close_finding' finding.id %}">
<i class="fa-solid fa-fire-extinguisher"></i> Close Finding
Expand Down Expand Up @@ -1162,7 +1169,7 @@ <h4>Credential
</div>

<div class="protip">
<i class="fa-solid fa-lightbulb"></i> <strong>ProTip!</strong> Type <kbd>e</kbd> to edit any finding, <kbd>p</kbd> and <kbd>n</kbd> to navigate to the previous or next finding.
<i class="fa-solid fa-lightbulb"></i> <strong>ProTip!</strong> Type <kbd>e</kbd> to edit any finding, <kbd>p</kbd> and <kbd>n</kbd> to navigate to the previous or next finding, <kbd>v</kbd> to verify, and <kbd>c</kbd> to close the finding.
</div>
</div>
{% endblock %}
Expand All @@ -1175,6 +1182,9 @@ <h4>Credential
var firstID = {% if findings_list.0 %}{{findings_list.0}}{% else %}null{% endif %};
var currentID = {% if finding.id %}{{finding.id}}{% else %}null{% endif %};
var lastID = {% if findings_list_lastElement %}{{findings_list_lastElement}}{% else %}null{% endif %};
var canEditFinding = {% if finding|has_object_permission:"Finding_Edit" %}true{% else %}false{% endif %};
var findingIsMitigated = {% if finding.mitigated %}true{% else %}false{% endif %};
var findingIsVerified = {% if finding.verified %}true{% else %}false{% endif %};
if(currentID != firstID)
{
$('.PrevAndNext_Buttons').append('<a href="{% url 'view_finding' prev_finding_id %}" class="btn btn-primary">Previous Finding</a> ');
Expand Down Expand Up @@ -1254,6 +1264,34 @@ <h4>Credential
window.location.assign('{% url 'view_finding' next_finding_id %}');
});

$(document).on('keypress', null, 'v', function () {
if (!canEditFinding) {
alert('You do not have permission to verify this finding.');
return;
}
if (findingIsMitigated) {
alert('Finding is already closed and cannot be verified.');
return;
}
if (findingIsVerified) {
alert('Finding has already been verified.');
return;
}
window.location.assign('{% url 'verify_finding' finding.id %}');
});

$(document).on('keypress', null, 'c', function () {
if (!canEditFinding) {
alert('You do not have permission to close this finding.');
return;
}
if (findingIsMitigated) {
alert('Finding has already been closed.');
return;
}
window.location.assign('{% url 'close_finding' finding.id %}');
});

$('a.delete-finding').on('click', function (e) {
if (confirm('Are you sure you want to delete this finding?')) {
$("form#delete-finding-form").submit();
Expand Down