7 Commits

7 changed files with 19 additions and 33 deletions

View File

@ -19,7 +19,8 @@ description-editor-modal.html: The modal of the description editor
Author: imacat@mail.imacat.idv.tw (imacat) Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/28 First written: 2023/2/28
#} #}
<form id="accounting-description-editor-{{ description_editor.debit_credit }}" class="accounting-description-editor" name="accounting-dummy-form" data-debit-credit="{{ description_editor.debit_credit }}"> <form id="accounting-description-editor-{{ description_editor.debit_credit }}" class="accounting-description-editor" data-debit-credit="{{ description_editor.debit_credit }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div id="accounting-description-editor-{{ description_editor.debit_credit }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-description-editor-{{ description_editor.debit_credit }}-modal-label" aria-hidden="true"> <div id="accounting-description-editor-{{ description_editor.debit_credit }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-description-editor-{{ description_editor.debit_credit }}-modal-label" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -19,7 +19,8 @@ journal-entry-line-item-editor-modal: The modal of the journal entry line item e
Author: imacat@mail.imacat.idv.tw (imacat) Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/25 First written: 2023/2/25
#} #}
<form id="accounting-line-item-editor" name="accounting-dummy-form"> <form id="accounting-line-item-editor">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div id="accounting-line-item-editor-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-line-item-editor-modal-label" aria-hidden="true"> <div id="accounting-line-item-editor-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-line-item-editor-modal-label" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -19,7 +19,8 @@ recurring-item-editor-modal.html: The modal of the recurring item editor
Author: imacat@mail.imacat.idv.tw (imacat) Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/3/22 First written: 2023/3/22
#} #}
<form id="accounting-recurring-item-editor-{{ expense_income }}" name="accounting-dummy-form"> <form id="accounting-recurring-item-editor-{{ expense_income }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div id="accounting-recurring-item-editor-{{ expense_income }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-recurring-item-editor-{{ expense_income }}-modal-label" aria-hidden="true"> <div id="accounting-recurring-item-editor-{{ expense_income }}-modal" class="modal fade" tabindex="-1" aria-labelledby="accounting-recurring-item-editor-{{ expense_income }}-modal-label" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -41,7 +41,7 @@ def inherit_next(uri: str) -> str:
:param uri: The URI. :param uri: The URI.
:return: The URI with the current next URI added at the query argument. :return: The URI with the current next URI added at the query argument.
""" """
next_uri: str | None = __get_next_uri() next_uri: str | None = __get_next()
return uri if next_uri is None else __set_next(uri, next_uri) return uri if next_uri is None else __set_next(uri, next_uri)
@ -51,11 +51,11 @@ def or_next(uri: str) -> str:
:param uri: The URI. :param uri: The URI.
:return: The next URI or the supplied URI. :return: The next URI or the supplied URI.
""" """
next_uri: str | None = __get_next_uri() next_uri: str | None = __get_next()
return uri if next_uri is None else next_uri return uri if next_uri is None else next_uri
def __get_next_uri() -> str | None: def __get_next() -> str | None:
"""Returns the valid next URI. """Returns the valid next URI.
:return: The valid next URI. :return: The valid next URI.
@ -64,8 +64,6 @@ def __get_next_uri() -> str | None:
if request.method == "POST" else request.args.get("next") if request.method == "POST" else request.args.get("next")
if next_uri is None or not next_uri.startswith("/"): if next_uri is None or not next_uri.startswith("/"):
return None return None
if len(next_uri) > 512:
return next_uri[:512]
return next_uri return next_uri

View File

@ -25,9 +25,9 @@ First written: 2023/1/27
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="{{ "imacat" }}" /> <meta name="author" content="{{ "imacat" }}" />
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.4.0/css/all.min.css" integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@eonasdan/tempus-dominus@6.7.7/dist/css/tempus-dominus.min.css" crossorigin="anonymous"> <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/@eonasdan/tempus-dominus@6.7.7/dist/css/tempus-dominus.min.css" integrity="sha384-l66rSL7gUubrdJxFRbXUo/tO7eNPAcCiZXFs/Xl147146xNqQ1qt4oPW6jlVezsS" crossorigin="anonymous">
{% block styles %}{% endblock %} {% block styles %}{% endblock %}
<script src="{{ url_for("babel_catalog") }}"></script> <script src="{{ url_for("babel_catalog") }}"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
@ -121,10 +121,10 @@ First written: 2023/1/27
{% if messages %} {% if messages %}
{% for category, message in messages %} {% for category, message in messages %}
{% if category == "success" %} {% if category == "success" %}
<div class="alert alert-success alert-dismissible fade show" role="alert"> <div class="alert alert-success alert-dismissible fade show" role="alert">
{{ message }} {{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
{% elif category == "error" %} {% elif category == "error" %}
<div class="alert alert-danger alert-dismissible fade show" role="alert"> <div class="alert alert-danger alert-dismissible fade show" role="alert">
<strong>{{ _("Error:") }}</strong> {{ message }} <strong>{{ _("Error:") }}</strong> {{ message }}

View File

@ -140,21 +140,6 @@ class NextUriTestCase(unittest.TestCase):
"next": next_uri}) "next": next_uri})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# An extremely-long URI to trigger the error
next_uri = "/" + "x" * 1024
expected2 = next_uri[:512]
expected1 = f"{self.TARGET}?next={quote_plus(expected2)}"
response = client.get(f"/test-invalid-next?next={quote_plus(next_uri)}"
f"&inherit-expected={quote_plus(expected1)}"
f"&or-expected={quote_plus(expected2)}")
self.assertEqual(response.status_code, 200)
response = client.post("/test-invalid-next"
f"?inherit-expected={quote_plus(expected1)}"
f"&or-expected={quote_plus(expected2)}",
data={"csrf_token": csrf_token,
"next": next_uri})
self.assertEqual(response.status_code, 200)
class QueryKeywordParserTestCase(unittest.TestCase): class QueryKeywordParserTestCase(unittest.TestCase):
"""The test case for the query keyword parser.""" """The test case for the query keyword parser."""

View File

@ -71,9 +71,9 @@ def create_test_app() -> Flask:
"""The test view to return the CSRF token.""" """The test view to return the CSRF token."""
return render_template_string("{{csrf_token()}}") return render_template_string("{{csrf_token()}}")
@app.get("/.errors") @app.get("/.messages")
def get_errors_view() -> str: def get_messages_view() -> str:
"""The test view to return the CSRF token.""" """The test view to return the flashed messages."""
return render_template_string("{{get_flashed_messages()|tojson}}") return render_template_string("{{get_flashed_messages()|tojson}}")
return app return app