Skip to content

Commit f2b58b4

Browse files
committed
Fix URL redirection from remote source
Fixes #1518
1 parent 849a1b9 commit f2b58b4

4 files changed

Lines changed: 28 additions & 6 deletions

File tree

course/templates/course/_course_menu.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ <h4 class="course-menu-label">{% translate "COURSE_STAFF" %}</h4>
188188

189189
{% if is_course_staff %}
190190
<li class="nav-item">
191-
<a class="nav-link menu-pseudonymize" href="{% url 'toggle-pseudonymization' %}">
191+
<a class="nav-link menu-pseudonymize" href="{% url 'toggle-pseudonymization' %}?next={{ request.get_full_path|urlencode }}">
192192
{% if pseudonymize %}
193193
<i class="bi-eye-fill" aria-hidden="true" data-bs-toggle="tooltip" data-bs-placement="right" title="{% translate "UNPSEUDONYMIZE" %}"></i>
194194
<span class="course-menu-label">{% translate "UNPSEUDONYMIZE" %}</span>

exercise/templates/exercise/staff/_assessment_panel.html

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
{% for tag in submission.submission_taggings.all %}
3232
<form method="post" action="{% url 'remove-tag-from-submissions' course_slug=course.url instance_slug=instance.url module_slug=module.url exercise_path=exercise.get_path submission_id=submission.id subtag_id=tag.tag.id %}">
3333
{% csrf_token %}
34+
<input type="hidden" name="next" value="{{ request.get_full_path|urlencode }}">
3435
<div class="d-flex flex-nowrap align-items-center gap-1">
3536
{{tag.tag|colortag:"size=sm"}}
3637
<button type="submit" class="aplus-button--danger aplus-button--secondary aplus-button--xs"><i class="bi-x-lg" aria-hidden="true"></i></button>
@@ -40,7 +41,7 @@
4041
</p>
4142
</div>
4243
<div class="d-flex flex-wrap justify-content-end align-items-center gap-2">
43-
<div class="dropdown">
44+
<div id="taggingsDropdown" class="dropdown" data-next-path="{{ request.get_full_path|urlencode }}">
4445
<button class="aplus-button--secondary aplus-button--sm dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
4546
{% translate 'ADD_TAGGING' %}
4647
</button>
@@ -239,6 +240,16 @@
239240
csrfInput.setAttribute('value', csrfToken);
240241
form.appendChild(csrfInput);
241242

243+
// Read the next URL from a data attribute on the dropdown container
244+
var next = document.querySelector('#taggingsDropdown')?.getAttribute('data-next-path');
245+
if (next) {
246+
var nextInput = document.createElement('input');
247+
nextInput.setAttribute('type', 'hidden');
248+
nextInput.setAttribute('name', 'next');
249+
nextInput.setAttribute('value', next);
250+
form.appendChild(nextInput);
251+
}
252+
242253
form.submit();
243254
}
244255

exercise/views.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from django.shortcuts import get_object_or_404, redirect
99
from django.template.loader import render_to_string
1010
from django.utils.decorators import method_decorator
11+
from django.utils.http import url_has_allowed_host_and_scheme
1112
from django.utils.translation import gettext_lazy as _, get_language
1213
from django.utils.text import format_lazy
1314
from django.views.decorators.clickjacking import xframe_options_exempt
@@ -62,8 +63,10 @@ def post(self, request, *args, **kwargs):
6263
SubmissionTagging.objects.create(submission=submission, tag=subtag)
6364

6465
# Redirect back to the previous page
65-
return redirect(request.headers.get('referer', '/'))
66-
66+
next_url = request.POST.get('next')
67+
if next_url and url_has_allowed_host_and_scheme(next_url, allowed_hosts=None):
68+
return redirect(next_url)
69+
return redirect('/')
6770

6871
class SubmissionTaggingRemoveView(CourseInstanceBaseView):
6972
access_mode = ACCESS.ASSISTANT
@@ -80,7 +83,10 @@ def post(self, request, *args, **kwargs):
8083
SubmissionTagging.objects.filter(submission=submission, tag=subtag).delete()
8184

8285
# Redirect back to the previous page
83-
return redirect(request.headers.get('referer', '/'))
86+
next_url = request.POST.get('next')
87+
if next_url and url_has_allowed_host_and_scheme(next_url, allowed_hosts=None):
88+
return redirect(next_url)
89+
return redirect('/')
8490

8591

8692
class ExerciseInfoView(ExerciseBaseView):

userprofile/views.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,4 +368,9 @@ class PseudonymizeView(BaseView):
368368
def get(self, request: HttpRequest) -> HttpResponse:
369369
pseudonymize = request.session.get("pseudonymize", False)
370370
request.session["pseudonymize"] = not pseudonymize
371-
return HttpResponseRedirect(request.headers.get("referer", "/"))
371+
372+
# Redirect back to the previous page
373+
next_url = request.GET.get('next')
374+
if next_url and url_has_allowed_host_and_scheme(next_url, allowed_hosts=None):
375+
return HttpResponseRedirect(next_url)
376+
return HttpResponseRedirect('/')

0 commit comments

Comments
 (0)