mirror of
https://github.com/sissbruecker/linkding
synced 2024-11-21 19:03:02 +00:00
Return client error status code for invalid form submissions (#849)
* Returns client error status code for invalid form submissions * fix flaky test
This commit is contained in:
parent
d4006026db
commit
c3a2305a5f
7 changed files with 43 additions and 10 deletions
|
@ -26,6 +26,11 @@ class BookmarkEditViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
}
|
}
|
||||||
return {**form_data, **overrides}
|
return {**form_data, **overrides}
|
||||||
|
|
||||||
|
def test_should_render_successfully(self):
|
||||||
|
bookmark = self.setup_bookmark()
|
||||||
|
response = self.client.get(reverse("bookmarks:edit", args=[bookmark.id]))
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_should_edit_bookmark(self):
|
def test_should_edit_bookmark(self):
|
||||||
bookmark = self.setup_bookmark()
|
bookmark = self.setup_bookmark()
|
||||||
form_data = self.create_form_data({"id": bookmark.id})
|
form_data = self.create_form_data({"id": bookmark.id})
|
||||||
|
@ -46,6 +51,14 @@ class BookmarkEditViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
self.assertEqual(tags[0].name, "editedtag1")
|
self.assertEqual(tags[0].name, "editedtag1")
|
||||||
self.assertEqual(tags[1].name, "editedtag2")
|
self.assertEqual(tags[1].name, "editedtag2")
|
||||||
|
|
||||||
|
def test_should_return_422_with_invalid_form(self):
|
||||||
|
bookmark = self.setup_bookmark()
|
||||||
|
form_data = self.create_form_data({"id": bookmark.id, "url": ""})
|
||||||
|
response = self.client.post(
|
||||||
|
reverse("bookmarks:edit", args=[bookmark.id]), form_data
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 422)
|
||||||
|
|
||||||
def test_should_edit_unread_state(self):
|
def test_should_edit_unread_state(self):
|
||||||
bookmark = self.setup_bookmark()
|
bookmark = self.setup_bookmark()
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,11 @@ class BookmarkNewViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
self.assertEqual(tags[0].name, "tag1")
|
self.assertEqual(tags[0].name, "tag1")
|
||||||
self.assertEqual(tags[1].name, "tag2")
|
self.assertEqual(tags[1].name, "tag2")
|
||||||
|
|
||||||
|
def test_should_return_422_with_invalid_form(self):
|
||||||
|
form_data = self.create_form_data({"url": ""})
|
||||||
|
response = self.client.post(reverse("bookmarks:new"), form_data)
|
||||||
|
self.assertEqual(response.status_code, 422)
|
||||||
|
|
||||||
def test_should_create_new_unread_bookmark(self):
|
def test_should_create_new_unread_bookmark(self):
|
||||||
form_data = self.create_form_data({"unread": True})
|
form_data = self.create_form_data({"unread": True})
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class PasswordChangeViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
|
|
||||||
response = self.client.post(reverse("change_password"), form_data)
|
response = self.client.post(reverse("change_password"), form_data)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 422)
|
||||||
self.assertIn("old_password", response.context_data["form"].errors)
|
self.assertIn("old_password", response.context_data["form"].errors)
|
||||||
|
|
||||||
def test_should_return_error_for_mismatching_new_password(self):
|
def test_should_return_error_for_mismatching_new_password(self):
|
||||||
|
@ -54,4 +55,5 @@ class PasswordChangeViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
|
|
||||||
response = self.client.post(reverse("change_password"), form_data)
|
response = self.client.post(reverse("change_password"), form_data)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 422)
|
||||||
self.assertIn("new_password2", response.context_data["form"].errors)
|
self.assertIn("new_password2", response.context_data["form"].errors)
|
||||||
|
|
|
@ -22,6 +22,7 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
if not overrides:
|
if not overrides:
|
||||||
overrides = {}
|
overrides = {}
|
||||||
form_data = {
|
form_data = {
|
||||||
|
"update_profile": "",
|
||||||
"theme": UserProfile.THEME_AUTO,
|
"theme": UserProfile.THEME_AUTO,
|
||||||
"bookmark_date_display": UserProfile.BOOKMARK_DATE_DISPLAY_RELATIVE,
|
"bookmark_date_display": UserProfile.BOOKMARK_DATE_DISPLAY_RELATIVE,
|
||||||
"bookmark_description_display": UserProfile.BOOKMARK_DESCRIPTION_DISPLAY_INLINE,
|
"bookmark_description_display": UserProfile.BOOKMARK_DESCRIPTION_DISPLAY_INLINE,
|
||||||
|
@ -195,6 +196,12 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
|
|
||||||
self.assertSuccessMessage(html, "Profile updated")
|
self.assertSuccessMessage(html, "Profile updated")
|
||||||
|
|
||||||
|
def test_update_profile_with_invalid_form_returns_422(self):
|
||||||
|
form_data = self.create_profile_form_data({"items_per_page": "-1"})
|
||||||
|
response = self.client.post(reverse("bookmarks:settings.update"), form_data)
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 422)
|
||||||
|
|
||||||
def test_update_profile_should_not_be_called_without_respective_form_action(self):
|
def test_update_profile_should_not_be_called_without_respective_form_action(self):
|
||||||
form_data = {
|
form_data = {
|
||||||
"theme": UserProfile.THEME_DARK,
|
"theme": UserProfile.THEME_DARK,
|
||||||
|
@ -217,7 +224,6 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
# Enabling favicons schedules update
|
# Enabling favicons schedules update
|
||||||
form_data = self.create_profile_form_data(
|
form_data = self.create_profile_form_data(
|
||||||
{
|
{
|
||||||
"update_profile": "",
|
|
||||||
"enable_favicons": True,
|
"enable_favicons": True,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -331,7 +337,6 @@ class SettingsGeneralViewTestCase(TestCase, BookmarkFactoryMixin):
|
||||||
# Enabling favicons schedules update
|
# Enabling favicons schedules update
|
||||||
form_data = self.create_profile_form_data(
|
form_data = self.create_profile_form_data(
|
||||||
{
|
{
|
||||||
"update_profile": "",
|
|
||||||
"enable_preview_images": True,
|
"enable_preview_images": True,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import secrets
|
||||||
import gzip
|
import gzip
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
|
@ -9,9 +10,10 @@ from bookmarks.services import singlefile
|
||||||
|
|
||||||
|
|
||||||
class SingleFileServiceTestCase(TestCase):
|
class SingleFileServiceTestCase(TestCase):
|
||||||
html_content = "<html><body><h1>Hello, World!</h1></body></html>"
|
def setUp(self):
|
||||||
html_filepath = "temp.html.gz"
|
self.html_content = "<html><body><h1>Hello, World!</h1></body></html>"
|
||||||
temp_html_filepath = "temp.html.gz.tmp"
|
self.html_filepath = secrets.token_hex(8) + ".html.gz"
|
||||||
|
self.temp_html_filepath = self.html_filepath + ".tmp"
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
if os.path.exists(self.html_filepath):
|
if os.path.exists(self.html_filepath):
|
||||||
|
|
|
@ -150,7 +150,6 @@ def convert_tag_string(tag_string: str):
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def new(request):
|
def new(request):
|
||||||
status = 200
|
|
||||||
initial_url = request.GET.get("url")
|
initial_url = request.GET.get("url")
|
||||||
initial_title = request.GET.get("title")
|
initial_title = request.GET.get("title")
|
||||||
initial_description = request.GET.get("description")
|
initial_description = request.GET.get("description")
|
||||||
|
@ -169,8 +168,6 @@ def new(request):
|
||||||
return HttpResponseRedirect(reverse("bookmarks:close"))
|
return HttpResponseRedirect(reverse("bookmarks:close"))
|
||||||
else:
|
else:
|
||||||
return HttpResponseRedirect(reverse("bookmarks:index"))
|
return HttpResponseRedirect(reverse("bookmarks:index"))
|
||||||
else:
|
|
||||||
status = 422
|
|
||||||
else:
|
else:
|
||||||
form = BookmarkForm()
|
form = BookmarkForm()
|
||||||
if initial_url:
|
if initial_url:
|
||||||
|
@ -186,6 +183,7 @@ def new(request):
|
||||||
if initial_mark_unread:
|
if initial_mark_unread:
|
||||||
form.initial["unread"] = "true"
|
form.initial["unread"] = "true"
|
||||||
|
|
||||||
|
status = 422 if request.method == "POST" and not form.is_valid() else 200
|
||||||
context = {
|
context = {
|
||||||
"form": form,
|
"form": form,
|
||||||
"auto_close": initial_auto_close,
|
"auto_close": initial_auto_close,
|
||||||
|
@ -216,9 +214,10 @@ def edit(request, bookmark_id: int):
|
||||||
|
|
||||||
form.initial["tag_string"] = build_tag_string(bookmark.tag_names, " ")
|
form.initial["tag_string"] = build_tag_string(bookmark.tag_names, " ")
|
||||||
|
|
||||||
|
status = 422 if request.method == "POST" and not form.is_valid() else 200
|
||||||
context = {"form": form, "bookmark_id": bookmark_id, "return_url": return_url}
|
context = {"form": form, "bookmark_id": bookmark_id, "return_url": return_url}
|
||||||
|
|
||||||
return render(request, "bookmarks/edit.html", context)
|
return render(request, "bookmarks/edit.html", context, status=status)
|
||||||
|
|
||||||
|
|
||||||
def remove(request, bookmark_id: int):
|
def remove(request, bookmark_id: int):
|
||||||
|
|
|
@ -40,6 +40,13 @@ class LinkdingLoginView(auth_views.LoginView):
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class LinkdingPasswordChangeView(auth_views.PasswordChangeView):
|
||||||
|
def form_invalid(self, form):
|
||||||
|
response = super().form_invalid(form)
|
||||||
|
response.status_code = 422
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("admin/", linkding_admin_site.urls),
|
path("admin/", linkding_admin_site.urls),
|
||||||
path(
|
path(
|
||||||
|
@ -50,7 +57,7 @@ urlpatterns = [
|
||||||
path("logout/", auth_views.LogoutView.as_view(), name="logout"),
|
path("logout/", auth_views.LogoutView.as_view(), name="logout"),
|
||||||
path(
|
path(
|
||||||
"change-password/",
|
"change-password/",
|
||||||
auth_views.PasswordChangeView.as_view(),
|
LinkdingPasswordChangeView.as_view(),
|
||||||
name="change_password",
|
name="change_password",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
|
|
Loading…
Reference in a new issue