diff --git a/CHANGELOG b/CHANGELOG index af14221db..81709e25b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,57 @@ This changelog is viewable on the web at https://docs.funkwhale.audio/changelog. .. towncrier +0.18.3 (2019-03-21) +------------------- + +Upgrade instructions are available at +https://docs.funkwhale.audio/index.html + + +Avoid mixed content when deploying mono-container behind proxy [Manual action required] +--------------------------------------------------------------------------------------- + +*You are only concerned if you use the mono-container docker deployment behind a reverse proxy* + +Because of `an issue in our mono-container configuration `_, users deploying Funkwhale via docker +using our `funkwhale/all-in-one` image could face some mixed content warnings (and possibly other troubles) +when browsing the Web UI. + +This is fixed in this release, but on existing deployments, you'll need to add ``NESTED_PROXY=1`` in your container +environment (either in your ``.env`` file, or via your container management tool), then recreate your funkwhale container. + + +Enhancements: + +- Added title on hover for truncated content (#766) +- Ask for confirmation before leaving upload page if there is a an upload in process (#630) +- Exclude in-place imported files from quota computation (#570) +- Truncate filename in library file table to ensure correct display of the table. (#735) + + +Bugfixes: + +- Avoid mixed content when deploying mono-container behind HTTPS proxy (thetarkus/docker-funkwhale#19) +- Display new notifications immediatly on notifications page (#729) +- Ensure cover art from uploaded files is picked up properly on existing albums (#757) +- Fixed a crash when federating a track with unspecified position +- Fixed broken Activity and Actor modules in django admin (#767) +- Fixed broken sample apache configuration (#764) +- Fixed constant and unpredictable reordering during file upload (#716) +- Fixed delivering of local activities causing unintended side effects, such as rollbacking changes (#737) +- Fixed escaping issues in translated strings (#652) +- Fixed saving moderation policy when clicking on "Cancel" (#751) +- i18n: Update page title when changing the App's language. (#511) +- Include disc number in Subsonic responses (#765) +- Do not send notification when rejecting a follow on a local library (#743) + + +Documentation: + +- Added documentation on mono-container docker upgrade (#713) +- Added documentation to set up let's encrypt certificate (#745) + + 0.18.2 (2019-02-13) ------------------- diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index d8fca1274..2722502c0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -358,343 +358,6 @@ Internationalization -------------------- We're using https://github.com/Polyconseil/vue-gettext to manage i18n in the project. -<<<<<<< HEAD -When working on the front-end, any end-user string should be marked as a translatable string, -with the proper context, as described below. - -Translations in HTML -^^^^^^^^^^^^^^^^^^^^ - -Translations in HTML use the ```` tag:: - - - -Anything between the `` and `` delimiters will be considered as a translatable string. -You can use variables in the translated string via the ``:translate-params="{var: 'value'}"`` directive, and reference them like this: -``val value is %{ value }``. - -For pluralization, you need to use ``translate-params`` in conjunction with ``translate-plural`` and ``translate-n``: - -- ``translate-params`` should contain the variable you're using for pluralization (which is usually shown to the user) -- ``translate-n`` should match the same variable -- The ```` delimiters contain the non-pluralized version of your string -- The ``translate-plural`` directive contains the pluralized version of your string - - -Translations in javascript -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Translations in javascript work by calling the ``this.$*gettext`` functions:: - - export default { - computed: { - strings () { - let tracksCount = 42 - let playButton = this.$pgettext('Sidebar/Player/Button/Verb, Short', 'Play') - let loginMessage = this.$pgettext('*/Login/Message', 'Welcome back %{ username }') - let addedMessage = this.$npgettext('*/Player/Message', 'One track was queued', '%{ count } tracks were queued', tracksCount) - console.log(this.$gettextInterpolate(addedMessage, {count: tracksCount})) - console.log(this.$gettextInterpolate(loginMessage, {username: 'alice'})) - } - } - } - -The first argument of the ``$pgettext`` and ``$npgettext`` functions is the string context. - -Contextualization -^^^^^^^^^^^^^^^^^ - -Translation contexts provided via the ``translate-context`` directive and the ``$pgettext`` and ``$npgettext`` are never shown to end users -but visible by Funkwhale translators. They help translators where and how the strings are used, -especially with short or ambiguous strings, like ``May``, which can refer a month or a verb. - -While we could in theory use free form context, like ``This string is inside a button, in the main page, and is a call to action``, -Funkwhale use a hierarchical structure to write contexts and keep them short and consistents accross the app. The previous context, -rewritten correctly would be: ``Content/Home/Button/Call to action``. - -This hierarchical structure is made of several parts: - -- The location part, which is required and refers to the big blocks found in Funkwhale UI where the translated string is displayed: - - ``Content`` - - ``Footer`` - - ``Head`` - - ``Menu`` - - ``Popup`` - - ``Sidebar`` - - ``*`` for strings that are not tied to a specific location - -- The feature part, which is required, and refers to the feature associated with the translated string: - - ``About`` - - ``Admin`` - - ``Album`` - - ``Artist`` - - ``Embed`` - - ``Home`` - - ``Login`` - - ``Library`` - - ``Moderation`` - - ``Player`` - - ``Playlist`` - - ``Profile`` - - ``Favorites`` - - ``Notifications`` - - ``Radio`` - - ``Search`` - - ``Settings`` - - ``Signup`` - - ``Track`` - - ``Queue`` - - ``*`` for strings that are not tied to a specific feature - -- The component part, which is required and refers to the type of element that contain the string: - - ``Button`` - - ``Card`` - - ``Checkbox`` - - ``Dropdown`` - - ``Error message`` - - ``Form`` - - ``Header`` - - ``Help text`` - - ``Hidden text`` - - ``Icon`` - - ``Input`` - - ``Image`` - - ``Label`` - - ``Link`` - - ``List item`` - - ``Menu`` - - ``Message`` - - ``Paragraph`` - - ``Placeholder`` - - ``Tab`` - - ``Table`` - - ``Title`` - - ``Tooltip`` - - ``*`` for strings that are not tied to a specific component - -The detail part, which is optional and refers to the contents of the string itself, such as: - - ``Adjective`` - - ``Call to action`` - - ``Noun`` - - ``Short`` - - ``Unit`` - - ``Verb`` - -Here are a few examples of valid context hierarchies: - -- ``Sidebar/Player/Button`` -- ``Content/Home/Button/Call to action`` -- ``Footer/*/Help text`` -- ``*/*/*/Verb, Short`` -- ``Popup/Playlist/Button`` -- ``Content/Admin/Table.Label/Short, Noun (Value is a date)`` - -It's possible to nest multiple component parts to reach a higher level of detail. The component parts are then separated by a dot: - -- ``Sidebar/Queue/Tab.Title`` -- ``Content/*/Button.Title`` -- ``Content/*/Table.Header`` -- ``Footer/*/List item.Link`` -- ``Content/*/Form.Help text`` - -Collecting translatable strings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you want to ensure your translatable strings are correctly marked for translation, -you can try to extract them. -||||||| merged common ancestors -When working on the front-end, any end-user string should be translated -using either ``yourstring`` or ``$gettext('yourstring')`` -function. -======= -<<<<<<< HEAD -When working on the front-end, any end-user string should be translated -using either ``yourstring`` or ``$gettext('yourstring')`` -function. -||||||| parent of 21fb39dd... Update docs/developers/index.rst, docs/developers/subsonic.rst files -When working on the front-end, any end-user string should be marked as a translatable string, -with the proper context, as described below. - -Translations in HTML -^^^^^^^^^^^^^^^^^^^^ - -Translations in HTML use the ```` tag:: - - - -Anything between the `` and `` delimiters will be considered as a translatable string. -You can use variables in the translated string via the ``:translate-params="{var: 'value'}"`` directive, and reference them like this: -``val value is %{ value }``. - -For pluralization, you need to use ``translate-params`` in conjunction with ``translate-plural`` and ``translate-n``: - -- ``translate-params`` should contain the variable you're using for pluralization (which is usually shown to the user) -- ``translate-n`` should match the same variable -- The ```` delimiters contain the non-pluralized version of your string -- The ``translate-plural`` directive contains the pluralized version of your string - - -Translations in javascript -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Translations in javascript work by calling the ``this.$*gettext`` functions:: - - export default { - computed: { - strings () { - let tracksCount = 42 - let playButton = this.$pgettext('Sidebar/Player/Button/Verb, Short', 'Play') - let loginMessage = this.$pgettext('*/Login/Message', 'Welcome back %{ username }') - let addedMessage = this.$npgettext('*/Player/Message', 'One track was queued', '%{ count } tracks were queued', tracksCount) - console.log(this.$gettextInterpolate(addedMessage, {count: tracksCount})) - console.log(this.$gettextInterpolate(loginMessage, {username: 'alice'})) - } - } - } - -The first argument of the ``$pgettext`` and ``$npgettext`` functions is the string context. - -Contextualization -^^^^^^^^^^^^^^^^^ - -Translation contexts provided via the ``translate-context`` directive and the ``$pgettext`` and ``$npgettext`` are never shown to end users -but visible by Funkwhale translators. They help translators where and how the strings are used, -especially with short or ambiguous strings, like ``May``, which can refer a month or a verb. - -While we could in theory use free form context, like ``This string is inside a button, in the main page, and is a call to action``, -Funkwhale use a hierarchical structure to write contexts and keep them short and consistents accross the app. The previous context, -rewritten correctly would be: ``Content/Home/Button/Call to action``. - -This hierarchical structure is made of several parts: - -- The location part, which is required and refers to the big blocks found in Funkwhale UI where the translated string is displayed: - - ``Content`` - - ``Footer`` - - ``Head`` - - ``Menu`` - - ``Popup`` - - ``Sidebar`` - - ``*`` for strings that are not tied to a specific location - -- The feature part, which is required, and refers to the feature associated with the translated string: - - ``About`` - - ``Admin`` - - ``Album`` - - ``Artist`` - - ``Embed`` - - ``Home`` - - ``Login`` - - ``Library`` - - ``Moderation`` - - ``Player`` - - ``Playlist`` - - ``Profile`` - - ``Favorites`` - - ``Notifications`` - - ``Radio`` - - ``Search`` - - ``Settings`` - - ``Signup`` - - ``Track`` - - ``Queue`` - - ``*`` for strings that are not tied to a specific feature - -- The component part, which is required and refers to the type of element that contain the string: - - ``Button`` - - ``Card`` - - ``Checkbox`` - - ``Dropdown`` - - ``Error message`` - - ``Form`` - - ``Header`` - - ``Help text`` - - ``Hidden text`` - - ``Icon`` - - ``Input`` - - ``Image`` - - ``Label`` - - ``Link`` - - ``List item`` - - ``Menu`` - - ``Message`` - - ``Paragraph`` - - ``Placeholder`` - - ``Tab`` - - ``Table`` - - ``Title`` - - ``Tooltip`` - - ``*`` for strings that are not tied to a specific component - -The detail part, which is optional and refers to the contents of the string itself, such as: - - ``Adjective`` - - ``Call to action`` - - ``Noun`` - - ``Short`` - - ``Unit`` - - ``Verb`` - -Here are a few examples of valid context hierarchies: - -- ``Sidebar/Player/Button`` -- ``Content/Home/Button/Call to action`` -- ``Footer/*/Help text`` -- ``*/*/*/Verb, Short`` -- ``Popup/Playlist/Button`` -- ``Content/Admin/Table.Label/Short, Noun (Value is a date)`` - -It's possible to nest multiple component parts to reach a higher level of detail. The component parts are then separated by a dot: - -- ``Sidebar/Queue/Tab.Title`` -- ``Content/*/Button.Title`` -- ``Content/*/Table.Header`` -- ``Footer/*/List item.Link`` -- ``Content/*/Form.Help text`` - -Collecting translatable strings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If you want to ensure your translatable strings are correctly marked for translation, -you can try to extract them. When working on the front-end, any end-user string should be marked as a translatable string, with the proper context, as described below. diff --git a/api/funkwhale_api/__init__.py b/api/funkwhale_api/__init__.py index 5038f371a..cfadc246c 100644 --- a/api/funkwhale_api/__init__.py +++ b/api/funkwhale_api/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -__version__ = "0.18.2" +__version__ = "0.18.3" __version_info__ = tuple( [ int(num) if num.isdigit() else num diff --git a/api/funkwhale_api/common/models.py b/api/funkwhale_api/common/models.py index c277fb9df..efb2cf4fe 100644 --- a/api/funkwhale_api/common/models.py +++ b/api/funkwhale_api/common/models.py @@ -5,12 +5,25 @@ from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType from django.conf import settings from django.db import models, transaction +from django.db.models import Lookup +from django.db.models.fields import Field from django.utils import timezone from django.urls import reverse from funkwhale_api.federation import utils as federation_utils +@Field.register_lookup +class NotEqual(Lookup): + lookup_name = "ne" + + def as_sql(self, compiler, connection): + lhs, lhs_params = self.process_lhs(compiler, connection) + rhs, rhs_params = self.process_rhs(compiler, connection) + params = lhs_params + rhs_params + return "%s <> %s" % (lhs, rhs), params + + class LocalFromFidQuerySet: def local(self, include=True): host = settings.FEDERATION_HOSTNAME diff --git a/api/funkwhale_api/federation/models.py b/api/funkwhale_api/federation/models.py index 03e9560a5..ba1ae3e08 100644 --- a/api/funkwhale_api/federation/models.py +++ b/api/funkwhale_api/federation/models.py @@ -53,11 +53,15 @@ class ActorQuerySet(models.QuerySet): def with_current_usage(self): qs = self for s in ["pending", "skipped", "errored", "finished"]: + uploads_query = models.Q( + libraries__uploads__import_status=s, + libraries__uploads__audio_file__isnull=False, + libraries__uploads__audio_file__ne="", + ) qs = qs.annotate( **{ "_usage_{}".format(s): models.Sum( - "libraries__uploads__size", - filter=models.Q(libraries__uploads__import_status=s), + "libraries__uploads__size", filter=uploads_query ) } ) diff --git a/api/tests/federation/test_models.py b/api/tests/federation/test_models.py index f59293b67..6eeebd660 100644 --- a/api/tests/federation/test_models.py +++ b/api/tests/federation/test_models.py @@ -53,7 +53,25 @@ def test_actor_get_quota(factories): audio_file__from_path=None, audio_file__data=b"aaaa", ) - expected = {"total": 10, "pending": 1, "skipped": 2, "errored": 3, "finished": 4} + + # this one is imported in place and don't count + factories["music.Upload"]( + library=library, + import_status="finished", + source="file://test", + audio_file=None, + size=42, + ) + # this one is imported in place but count because there is a mapped file + factories["music.Upload"]( + library=library, + import_status="finished", + source="file://test2", + audio_file__from_path=None, + audio_file__data=b"aaaa", + ) + + expected = {"total": 14, "pending": 1, "skipped": 2, "errored": 3, "finished": 8} assert library.actor.get_current_usage() == expected diff --git a/changes/changelog.d/511.bugfix b/changes/changelog.d/511.bugfix deleted file mode 100644 index 0c4b61375..000000000 --- a/changes/changelog.d/511.bugfix +++ /dev/null @@ -1 +0,0 @@ -i18n: Update page title when changing the App's language. (#511) diff --git a/changes/changelog.d/630.enhancement b/changes/changelog.d/630.enhancement deleted file mode 100644 index 019911337..000000000 --- a/changes/changelog.d/630.enhancement +++ /dev/null @@ -1 +0,0 @@ -Ask for confirmation before leaving upload page if there is a an upload in process (#630) \ No newline at end of file diff --git a/changes/changelog.d/652.bugfix b/changes/changelog.d/652.bugfix deleted file mode 100644 index da8d30b00..000000000 --- a/changes/changelog.d/652.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed escaping issues in translated strings (#652) diff --git a/changes/changelog.d/713.doc b/changes/changelog.d/713.doc deleted file mode 100644 index ad3db61a2..000000000 --- a/changes/changelog.d/713.doc +++ /dev/null @@ -1 +0,0 @@ -Added documentation on mono-container docker upgrade (#713) diff --git a/changes/changelog.d/716.bugfix b/changes/changelog.d/716.bugfix deleted file mode 100644 index 1b9b182c9..000000000 --- a/changes/changelog.d/716.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed constant and unpredictable reordering during file upload (#716) diff --git a/changes/changelog.d/729.bugfix b/changes/changelog.d/729.bugfix deleted file mode 100644 index a0209cb95..000000000 --- a/changes/changelog.d/729.bugfix +++ /dev/null @@ -1 +0,0 @@ -Display new notifications immediatly on notifications page (#729) diff --git a/changes/changelog.d/735.enhancement b/changes/changelog.d/735.enhancement deleted file mode 100644 index d6fb9ad70..000000000 --- a/changes/changelog.d/735.enhancement +++ /dev/null @@ -1 +0,0 @@ -Truncate filename in library file table to ensure correct display of the table. (#735) diff --git a/changes/changelog.d/737.bugfix b/changes/changelog.d/737.bugfix deleted file mode 100644 index c65050a6e..000000000 --- a/changes/changelog.d/737.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed delivering of local activities causing unintended side effects, such as rollbacking changes (#737) diff --git a/changes/changelog.d/743.bugfig b/changes/changelog.d/743.bugfig deleted file mode 100644 index 5a3ebea0c..000000000 --- a/changes/changelog.d/743.bugfig +++ /dev/null @@ -1 +0,0 @@ -Do not send notification when rejecting a follow on a local library (#743) diff --git a/changes/changelog.d/745.doc b/changes/changelog.d/745.doc deleted file mode 100644 index 1bdb784f3..000000000 --- a/changes/changelog.d/745.doc +++ /dev/null @@ -1 +0,0 @@ -Added documentation to set up let's encrypt certificate (#745) diff --git a/changes/changelog.d/751.bugfix b/changes/changelog.d/751.bugfix deleted file mode 100644 index f107e2c78..000000000 --- a/changes/changelog.d/751.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed saving moderation policy when clicking on "Cancel" (#751) diff --git a/changes/changelog.d/757.bugfix b/changes/changelog.d/757.bugfix deleted file mode 100644 index f9e9eae35..000000000 --- a/changes/changelog.d/757.bugfix +++ /dev/null @@ -1 +0,0 @@ -Ensure cover art from uploaded files is picked up properly on existing albums (#757) diff --git a/changes/changelog.d/764.bugfix b/changes/changelog.d/764.bugfix deleted file mode 100644 index 114f602b5..000000000 --- a/changes/changelog.d/764.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed broken sample apache configuration (#764) diff --git a/changes/changelog.d/765.bugfix b/changes/changelog.d/765.bugfix deleted file mode 100644 index 79872e1ed..000000000 --- a/changes/changelog.d/765.bugfix +++ /dev/null @@ -1 +0,0 @@ -Include disc number in Subsonic responses (#765) diff --git a/changes/changelog.d/766.enhancement b/changes/changelog.d/766.enhancement deleted file mode 100644 index 7aca9fb1c..000000000 --- a/changes/changelog.d/766.enhancement +++ /dev/null @@ -1 +0,0 @@ -Added title on hover for truncated content (#766) diff --git a/changes/changelog.d/767.bugfix b/changes/changelog.d/767.bugfix deleted file mode 100644 index 8a2bbdb86..000000000 --- a/changes/changelog.d/767.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed broken Activity and Actor modules in django admin (#767) diff --git a/changes/changelog.d/null-position.bugfix b/changes/changelog.d/null-position.bugfix deleted file mode 100644 index a3c7b5a02..000000000 --- a/changes/changelog.d/null-position.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed a crash when federating a track with unspecified position diff --git a/docs/installation/docker.rst b/docs/installation/docker.rst index 163c8555b..b6f67f5e4 100644 --- a/docs/installation/docker.rst +++ b/docs/installation/docker.rst @@ -53,6 +53,8 @@ Create an env file to store a few important configuration options: echo "FUNKWHALE_HOSTNAME=yourdomain.funkwhale" >> .env echo "FUNKWHALE_PROTOCOL=https" >> .env # or http echo "DJANGO_SECRET_KEY=$(openssl rand -hex 45)" >> .env # generate and store a secure secret key for your instance + # Remove this if you expose the container directly on ports 80/443 + echo "NESTED_PROXY=1" >> .env Then start the container: @@ -112,6 +114,31 @@ Useful commands: -d \ funkwhale/all-in-one:$FUNKWHALE_VERSION + + You can use the following docker-compose file to make the management process easier: + + .. code-block:: yaml + + version: "3" + + services: + funkwhale: + container_name: funkwhale + restart: unless-stopped + # add the version number in your .env file, or hardcode it + image: funkwhale/all-in-one:${FUNKWHALE_VERSION} + env_file: .env + environment: + # adapt to the pid/gid that own /srv/funkwhale/data + - PUID=1000 + - PGID=1000 + volumes: + - /srv/funkwhale/data:/data + - /path/to/your/music/dir:/music:ro + ports: + - "5000:80" + + .. _docker-multi-container: Multi-container installation