diff options
-rw-r--r-- | doc/administration/configuration.rst | 6 | ||||
-rw-r--r-- | fietsboek/actions.py | 11 | ||||
-rw-r--r-- | fietsboek/config.py | 3 | ||||
-rw-r--r-- | fietsboek/locale/de/LC_MESSAGES/messages.mo | bin | 15259 -> 15377 bytes | |||
-rw-r--r-- | fietsboek/locale/de/LC_MESSAGES/messages.po | 27 | ||||
-rw-r--r-- | fietsboek/locale/en/LC_MESSAGES/messages.mo | bin | 14269 -> 14369 bytes | |||
-rw-r--r-- | fietsboek/locale/en/LC_MESSAGES/messages.po | 27 | ||||
-rw-r--r-- | fietsboek/locale/fietslog.pot | 20 | ||||
-rw-r--r-- | fietsboek/templates/edit_form.jinja2 | 9 | ||||
-rw-r--r-- | tests/conftest.py | 9 | ||||
-rw-r--r-- | tests/playwright/conftest.py | 4 | ||||
-rw-r--r-- | tests/playwright/test_no_image_uploads.py | 34 |
12 files changed, 112 insertions, 38 deletions
diff --git a/doc/administration/configuration.rst b/doc/administration/configuration.rst index 5be3537..4d33b7f 100644 --- a/doc/administration/configuration.rst +++ b/doc/administration/configuration.rst @@ -42,13 +42,17 @@ Most of the configuration is in the ``[app:main]`` category and looks like this: General Settings ---------------- -Use ``enable_account_registration`` enable or disable the creation of new +Use ``enable_account_registration`` to enable or disable the creation of new accounts via the web interface, for example if you want to have a private instance. New accounts can always be created using the CLI management tool. Set ``session_key`` to a random string of characters. This is the key used to sign session data, so it should not get into wrong hands! +Use ``fietsboek.enable_image_uploads`` to enable or disable image uploads. By +default, track uploaders can add images to the track. Set this setting to +``false`` to disable this feature. + You can set up custom pages using ``fietsboek.pages``. See :doc:`custom-pages` for more information. diff --git a/fietsboek/actions.py b/fietsboek/actions.py index 7e83c22..439a8cd 100644 --- a/fietsboek/actions.py +++ b/fietsboek/actions.py @@ -139,7 +139,7 @@ def edit_images(request: Request, track: models.Track, *, manager: Optional[Trac if image_meta: request.dbsession.delete(image_meta) - # Add new images + # Add new images, but only if the setting allows for it set_descriptions = set() for param_name, image in request.params.items(): match = re.match("image\\[(\\d+)\\]$", param_name) @@ -150,6 +150,15 @@ def edit_images(request: Request, track: models.Track, *, manager: Optional[Trac continue upload_id = match.group(1) + + # If the uploads are disabled, we still add the image to + # set_descriptions so that later down below we don't try to set the + # description for it. + if not request.config.enable_image_uploads: + set_descriptions.add(upload_id) + LOGGER.debug("Tried to upload image but uploads are disabled (track %s)", track.id) + continue + image_name = manager.add_image(image.file, image.filename) image_meta = models.ImageMetadata(track=track, image_name=image_name) image_meta.description = request.params.get(f"image-description[{upload_id}]", "") diff --git a/fietsboek/config.py b/fietsboek/config.py index 6cb1f04..c3c31c8 100644 --- a/fietsboek/config.py +++ b/fietsboek/config.py @@ -148,6 +148,9 @@ class Config(BaseModel): enable_account_registration: bool = False """Enable registration of new accounts.""" + enable_image_uploads: bool = Field(True, alias="fietsboek.enable_image_uploads") + """Allow track uploaders to also upload images for tracks.""" + session_key: str """Session key.""" diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.mo b/fietsboek/locale/de/LC_MESSAGES/messages.mo Binary files differindex f2bf3ea..3c020df 100644 --- a/fietsboek/locale/de/LC_MESSAGES/messages.mo +++ b/fietsboek/locale/de/LC_MESSAGES/messages.mo diff --git a/fietsboek/locale/de/LC_MESSAGES/messages.po b/fietsboek/locale/de/LC_MESSAGES/messages.po index 69723be..24e1cb5 100644 --- a/fietsboek/locale/de/LC_MESSAGES/messages.po +++ b/fietsboek/locale/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2023-09-14 20:05+0200\n" +"POT-Creation-Date: 2023-11-10 22:23+0100\n" "PO-Revision-Date: 2022-07-02 17:35+0200\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language: de\n" @@ -18,11 +18,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.12.1\n" -#: fietsboek/actions.py:255 +#: fietsboek/actions.py:257 msgid "email.verify_mail.subject" msgstr "Fietsboek Konto Bestätigung" -#: fietsboek/actions.py:258 +#: fietsboek/actions.py:260 msgid "email.verify.text" msgstr "" "Um Dein Fietsboek-Konto zu bestätigen, nutze diesen Link: {}\n" @@ -471,23 +471,27 @@ msgid "page.track.form.description" msgstr "Beschreibung" #: fietsboek/templates/edit_form.jinja2:108 -#: fietsboek/templates/edit_form.jinja2:122 +#: fietsboek/templates/edit_form.jinja2:129 msgid "page.track.form.remove_image" msgstr "Bild entfernen" -#: fietsboek/templates/edit_form.jinja2:117 +#: fietsboek/templates/edit_form.jinja2:118 msgid "page.track.form.select_images" msgstr "Bilder auswählen" -#: fietsboek/templates/edit_form.jinja2:133 +#: fietsboek/templates/edit_form.jinja2:122 +msgid "page.track.form.image_uploads_disabled" +msgstr "Das Hochladen von Bildern ist auf diesem Fietsboek deaktiviert" + +#: fietsboek/templates/edit_form.jinja2:140 msgid "page.track.form.image_description_modal" msgstr "Bildbeschreibung" -#: fietsboek/templates/edit_form.jinja2:140 +#: fietsboek/templates/edit_form.jinja2:147 msgid "page.track.form.image_description_modal.save" msgstr "Übernehmen" -#: fietsboek/templates/edit_form.jinja2:166 +#: fietsboek/templates/edit_form.jinja2:173 msgid "page.track.form.transformer.enable" msgstr "Transformation anwenden" @@ -759,9 +763,10 @@ msgstr "Sitzungen abmelden" #: fietsboek/templates/user_data.jinja2:40 msgid "page.my_profile.session_logout.explanation" msgstr "" -"Mit dieser Funktion können alle Sitzungen beendet werden. Dies ist nützlich, " -"wenn Du vergessen hast, dich auf einem fremden Gerät abzumelden. Beachte, dass " -"Du dich erneut anmelden musst, wenn Du diese Funktion nutzt!" +"Mit dieser Funktion können alle Sitzungen beendet werden. Dies ist " +"nützlich, wenn Du vergessen hast, dich auf einem fremden Gerät " +"abzumelden. Beachte, dass Du dich erneut anmelden musst, wenn Du diese " +"Funktion nutzt!" #: fietsboek/templates/user_data.jinja2:44 msgid "page.my_profile.session_logout.button" diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.mo b/fietsboek/locale/en/LC_MESSAGES/messages.mo Binary files differindex da23e31..c03929b 100644 --- a/fietsboek/locale/en/LC_MESSAGES/messages.mo +++ b/fietsboek/locale/en/LC_MESSAGES/messages.mo diff --git a/fietsboek/locale/en/LC_MESSAGES/messages.po b/fietsboek/locale/en/LC_MESSAGES/messages.po index 45b15cc..f5a7874 100644 --- a/fietsboek/locale/en/LC_MESSAGES/messages.po +++ b/fietsboek/locale/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2023-09-14 20:05+0200\n" +"POT-Creation-Date: 2023-11-10 22:23+0100\n" "PO-Revision-Date: 2023-04-03 20:42+0200\n" "Last-Translator: \n" "Language: en\n" @@ -18,11 +18,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.12.1\n" -#: fietsboek/actions.py:255 +#: fietsboek/actions.py:257 msgid "email.verify_mail.subject" msgstr "Fietsboek Account Verification" -#: fietsboek/actions.py:258 +#: fietsboek/actions.py:260 msgid "email.verify.text" msgstr "" "To verify your Fietsboek account, please use this link: {}\n" @@ -467,23 +467,27 @@ msgid "page.track.form.description" msgstr "Description" #: fietsboek/templates/edit_form.jinja2:108 -#: fietsboek/templates/edit_form.jinja2:122 +#: fietsboek/templates/edit_form.jinja2:129 msgid "page.track.form.remove_image" msgstr "Remove image" -#: fietsboek/templates/edit_form.jinja2:117 +#: fietsboek/templates/edit_form.jinja2:118 msgid "page.track.form.select_images" msgstr "Select images" -#: fietsboek/templates/edit_form.jinja2:133 +#: fietsboek/templates/edit_form.jinja2:122 +msgid "page.track.form.image_uploads_disabled" +msgstr "Image uploads are disabled on this Fietsboek" + +#: fietsboek/templates/edit_form.jinja2:140 msgid "page.track.form.image_description_modal" msgstr "Image description" -#: fietsboek/templates/edit_form.jinja2:140 +#: fietsboek/templates/edit_form.jinja2:147 msgid "page.track.form.image_description_modal.save" msgstr "Apply" -#: fietsboek/templates/edit_form.jinja2:166 +#: fietsboek/templates/edit_form.jinja2:173 msgid "page.track.form.transformer.enable" msgstr "Apply transformation" @@ -753,9 +757,10 @@ msgstr "Invalidate sessions" #: fietsboek/templates/user_data.jinja2:40 msgid "page.my_profile.session_logout.explanation" msgstr "" -"With this functionality, you can force all of your current sessions " -"to be logged out. This is useful when you forgot to log out on a foreign " -"device. Note that you will have to log in again after using this function." +"With this functionality, you can force all of your current sessions to be" +" logged out. This is useful when you forgot to log out on a foreign " +"device. Note that you will have to log in again after using this " +"function." #: fietsboek/templates/user_data.jinja2:44 msgid "page.my_profile.session_logout.button" diff --git a/fietsboek/locale/fietslog.pot b/fietsboek/locale/fietslog.pot index b87785e..e5a0b40 100644 --- a/fietsboek/locale/fietslog.pot +++ b/fietsboek/locale/fietslog.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2023-09-14 20:05+0200\n" +"POT-Creation-Date: 2023-11-10 22:23+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -17,11 +17,11 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.12.1\n" -#: fietsboek/actions.py:255 +#: fietsboek/actions.py:257 msgid "email.verify_mail.subject" msgstr "" -#: fietsboek/actions.py:258 +#: fietsboek/actions.py:260 msgid "email.verify.text" msgstr "" @@ -461,23 +461,27 @@ msgid "page.track.form.description" msgstr "" #: fietsboek/templates/edit_form.jinja2:108 -#: fietsboek/templates/edit_form.jinja2:122 +#: fietsboek/templates/edit_form.jinja2:129 msgid "page.track.form.remove_image" msgstr "" -#: fietsboek/templates/edit_form.jinja2:117 +#: fietsboek/templates/edit_form.jinja2:118 msgid "page.track.form.select_images" msgstr "" -#: fietsboek/templates/edit_form.jinja2:133 -msgid "page.track.form.image_description_modal" +#: fietsboek/templates/edit_form.jinja2:122 +msgid "page.track.form.image_uploads_disabled" msgstr "" #: fietsboek/templates/edit_form.jinja2:140 +msgid "page.track.form.image_description_modal" +msgstr "" + +#: fietsboek/templates/edit_form.jinja2:147 msgid "page.track.form.image_description_modal.save" msgstr "" -#: fietsboek/templates/edit_form.jinja2:166 +#: fietsboek/templates/edit_form.jinja2:173 msgid "page.track.form.transformer.enable" msgstr "" diff --git a/fietsboek/templates/edit_form.jinja2 b/fietsboek/templates/edit_form.jinja2 index 1abe076..43f3400 100644 --- a/fietsboek/templates/edit_form.jinja2 +++ b/fietsboek/templates/edit_form.jinja2 @@ -114,7 +114,14 @@ {% endfor %} </div> <input type="file" name="image[]" id="imageSelector" class="form-control" accept="image/*" style="display:none;" multiple> - <button type="button" onclick="document.querySelector('#imageSelector').click()" class="btn btn-primary"><i class="bi bi-images"></i> {{ _("page.track.form.select_images") }}</button> + <button type="button" onclick="document.querySelector('#imageSelector').click()" class="btn btn-primary" id="selectImagesButton" {% if not request.config.enable_image_uploads %}disabled{% endif %}> + <i class="bi bi-images"></i> {{ _("page.track.form.select_images") }} + </button> + {% if not request.config.enable_image_uploads %} + <span class="text-info"> + <i class="bi bi-info-circle-fill"></i> {{ _("page.track.form.image_uploads_disabled") }} + </span> + {% endif %} </div> <!-- Mode hidden templates --> <div style="display:none;"> diff --git a/tests/conftest.py b/tests/conftest.py index a4366ab..94f795a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,11 +28,14 @@ def ini_file(request): # potentially grab this path from a pytest option return os.path.abspath(request.config.option.ini or 'testing.ini') -@pytest.fixture(scope='session') +# Even though the ini file is scoped to session, we scope the actual settings +# to module only. This way, we can test different configurations in different +# modules. +@pytest.fixture(scope='module') def app_settings(ini_file): return get_appsettings(ini_file) -@pytest.fixture(scope='session') +@pytest.fixture(scope='module') def dbengine(app_settings, ini_file): engine = models.get_engine(app_settings) @@ -73,7 +76,7 @@ def _cleanup_data(app_settings): if (data_dir / "tracks").is_dir(): shutil.rmtree(data_dir / "tracks") -@pytest.fixture(scope='session') +@pytest.fixture(scope='module') def app(app_settings, dbengine, tmp_path_factory): app_settings["fietsboek.data_dir"] = str(tmp_path_factory.mktemp("data")) logging.getLogger().setLevel(logging.DEBUG) diff --git a/tests/playwright/conftest.py b/tests/playwright/conftest.py index 12a0047..4e7f5a4 100644 --- a/tests/playwright/conftest.py +++ b/tests/playwright/conftest.py @@ -15,7 +15,7 @@ from fietsboek.config import Config import pytest -@pytest.fixture(scope="session") +@pytest.fixture(scope="module") def server_port(): """Return a (likely) free port. @@ -29,7 +29,7 @@ def server_port(): return port -@pytest.fixture(scope="session", autouse=True) +@pytest.fixture(scope="module", autouse=True) def running_server(server_port, app): """Have the app running as an actual server.""" server = simple_server.make_server("127.0.0.1", server_port, app) diff --git a/tests/playwright/test_no_image_uploads.py b/tests/playwright/test_no_image_uploads.py new file mode 100644 index 0000000..b133697 --- /dev/null +++ b/tests/playwright/test_no_image_uploads.py @@ -0,0 +1,34 @@ +import pytest +from playwright.sync_api import Page, expect + +from testutils import extract_and_upload + + +@pytest.fixture(scope="module") +def app_settings(app_settings): + """Override the standard app settings to disable image uploads.""" + app_settings["fietsboek.enable_image_uploads"] = "false" + return app_settings + + +def test_image_button_disabled_during_upload(page: Page, playwright_helper, tmp_path, dbaccess): + playwright_helper.login() + + page.goto("/") + page.get_by_text("Upload").click() + + # We unpack one of the test GPX files + extract_and_upload(page, "Teasi_1.gpx.gz", tmp_path) + + # We now fill in most of the data + expect(page.locator("#selectImagesButton")).to_be_disabled() + + +def test_image_button_disabled_during_edit(page: Page, playwright_helper, dbaccess): + playwright_helper.login() + track_id = playwright_helper.add_track().id + + page.goto(f"/track/{track_id}") + page.locator(".btn", has_text="Edit").click() + + expect(page.locator("#selectImagesButton")).to_be_disabled() |