Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions pkgs/by-name/funkwhale/fix-allauth-internal-function-use.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
diff --git a/funkwhale_api/users/views.py b/funkwhale_api/users/views.py
index 329f9e8d3..51ac0a5fc 100644
--- a/funkwhale_api/users/views.py
+++ b/funkwhale_api/users/views.py
@@ -1,7 +1,7 @@
import json

from allauth.account.adapter import get_adapter
-from allauth.account.utils import send_email_confirmation
+from allauth.account.models import EmailAddress
from dj_rest_auth import views as rest_auth_views
from dj_rest_auth.registration import views as registration_views
from django import http
@@ -39,7 +39,8 @@ class RegisterView(registration_views.RegisterView):
user = super().perform_create(serializer)
if not user.is_active:
# manual approval, we need to send the confirmation e-mail by hand
- send_email_confirmation(self.request, user)
+ email = EmailAddress.objects.get(user=user)
+ email.send_confirmation(request=self.request)
if user.invitation:
user.invitation.set_invited_user(user)

34 changes: 34 additions & 0 deletions pkgs/by-name/funkwhale/fix-oob-schemes.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
diff --git a/funkwhale_api/users/models.py b/funkwhale_api/users/models.py
index bb9348f8b..59734501f 100644
--- a/funkwhale_api/users/models.py
+++ b/funkwhale_api/users/models.py
@@ -7,6 +7,7 @@ import uuid
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import UserManager as BaseUserManager
+from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db.models import JSONField
from django.dispatch import receiver
@@ -387,9 +388,20 @@ OOB_SCHEMES = ["urn:ietf:wg:oauth:2.0:oob", "urn:ietf:wg:oauth:2.0:oob:auto"]

class CustomRedirectURIValidator(oauth2_validators.AllowedURIValidator):
def __call__(self, value):
+ if not value.startswith("urn:ietf:wg:oauth:2.0"):
+ return super().__call__(value)
+
if value in OOB_SCHEMES:
return value
- return super().__call__(value)
+
+ try:
+ oauth2_validators.URIValidator.__call__(self, value)
+ except ValidationError as e:
+ raise ValidationError(
+ "%(name)s URI validation error. %(cause)s: %(value)s",
+ params={"name": self.name, "value": value, "cause": e},
+ )
+


oauth2_models.AllowedURIValidator = CustomRedirectURIValidator
36 changes: 36 additions & 0 deletions pkgs/by-name/funkwhale/fix-root-filesystem-tests.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
diff --git a/pyproject.toml b/pyproject.toml
index 23453fe10..05c15eeed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -187,7 +187,7 @@ env = [
]

[tool.coverage.run]
-plugins = ["django_coverage_plugin"]
+plugins = ["django_coverage_plugin", "pyfakefs"]
source = ["funkwhale_api"]
omit = [
"*migrations*",
diff --git a/tests/music/test_views.py b/tests/music/test_views.py
index 3fb2b3341..1a0fef505 100644
--- a/tests/music/test_views.py
+++ b/tests/music/test_views.py
@@ -20,6 +20,10 @@ from funkwhale_api.users import authentication as users_authentication

DATA_DIR = os.path.dirname(os.path.abspath(__file__))

[email protected]
+def fake_fs(fs):
+ fs.add_real_directory(DATA_DIR)
+ yield fs

def test_artist_list_serializer(api_request, factories, logged_in_api_client):
tags = ["tag1", "tag2"]
@@ -290,6 +294,7 @@ def test_serve_file_in_place_utf8(
assert path == expected.encode("utf-8")


[email protected]("fake_fs")
@pytest.mark.parametrize(
"proxy,serve_path,expected",
[
231 changes: 231 additions & 0 deletions pkgs/by-name/funkwhale/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
{
lib,
python3,
fetchFromGitLab,
postgresql,
postgresqlTestHook,
redisTestHook,
funkwhale,
runCommand,

# Frontend
stdenv,
fetchYarnDeps,
yarnConfigHook,
yarnBuildHook,
nodejs,

nix-update-script,
}:
let
python = python3;

meta = {
description = "Federated platform for audio streaming, exploration, and publishing";
homepage = "https://www.funkwhale.audio/";
changelog = "https://docs.funkwhale.audio/changelog.html";
license = lib.licenses.agpl3Only;
teams = [ lib.teams.ngi ];
mainProgram = "funkwhale-manage";
};
in
python3.pkgs.buildPythonApplication rec {
pname = "funkwhale";
version = "2.0.0-alpha.2";
pyproject = true;

src = fetchFromGitLab {
domain = "dev.funkwhale.audio";
owner = "funkwhale";
repo = "funkwhale";
tag = version;
hash = "sha256-4WvTyVqFuSlkim/9S88tutvXJqA4VHsILH5q4WKsjo8=";
};
sourceRoot = "${src.name}/api";

patches = [
# `unicode-slugify` was removed from nixpkgs.
# See https://github.com/NixOS/nixpkgs/pull/448893.
./replace-unicode-slugify.patch

# The function was removed in an update.
./fix-allauth-internal-function-use.patch

# Broken in <https://github.com/django-oauth/django-oauth-toolkit/commit/13f0aceb010eececfb581a0e21f013f47a8f5f6b#diff-a7fb1c13746762fee6dcacf6b9f28079ef7f1567104660aa5a8d6ca388ccc838R123-R130>
./fix-oob-schemes.patch

./fix-root-filesystem-tests.patch
];

build-system = with python.pkgs; [
poetry-core
];

# Everything is pinned to specific versions.
pythonRelaxDeps = true;
pythonRemoveDeps = [
# Not used directly.
"gunicorn"
];

dependencies =
with python.pkgs;
[
# Django
dj-rest-auth
django
django-allauth
django-cache-memoize
django-cacheops
django-cleanup
django-cors-headers
django-dynamic-preferences
django-environ
django-filter
django-oauth-toolkit
django-redis
django-storages
django-versatileimagefield
djangorestframework
drf-spectacular
markdown
persisting-theory
psycopg2-binary
redis

# Django LDAP
django-auth-ldap
python-ldap

# Channels
channels
channels-redis

# Celery
kombu
celery

# Deployment
uvicorn

# Libs
aiohttp
arrow
bleach
boto3
click
cryptography
defusedxml
feedparser
python-ffmpeg
liblistenbrainz
musicbrainzngs
mutagen
pillow
pyld
python-magic
requests
requests-http-message-signatures
sentry-sdk
watchdog
troi
lb-matching-tools
unidecode
pycountry

# Typesense
typesense

ipython
pluralizer
service-identity
python-slugify
]
++ channels.optional-dependencies.daphne
++ uvicorn.optional-dependencies.standard;

nativeCheckInputs = with python.pkgs; [
postgresql
postgresqlTestHook
redisTestHook
pyfakefs
aioresponses
factory-boy
faker
ipdb
pytest
pytest-asyncio
prompt-toolkit
pytest-django
pytest-env
pytest-mock
pytest-randomly
pytest-sugar
requests-mock
django-extensions
];

postgresqlTestUserOptions = "LOGIN SUPERUSER";
checkPhase = ''
runHook preCheck

DATABASE_URL="postgresql://$PGUSER@$PGHOST/$PGDATABASE" \
FUNKWHALE_URL="https://example.com" \
DJANGO_SETTINGS_MODULE="config.settings.local" \
CACHE_URL="redis://$REDIS_SOCKET:6379/0" \
pytest

runHook postCheck
'';

passthru = {
inherit python;

static = runCommand "funkwhale-static" { } ''
FUNKWHALE_URL="https://example.com" \
DJANGO_SECRET_KEY="" \
STATIC_ROOT="$out" \
${lib.getExe funkwhale} collectstatic --no-input
'';

frontend = stdenv.mkDerivation {
pname = "funkwhale-frontend";
inherit version src;
sourceRoot = "${src.name}/front";

yarnOfflineCache = fetchYarnDeps {
yarnLock = "${src}/front/yarn.lock";
hash = "sha256-+rGiKBg18XL6W5b5VaYAbwbF+kQGX8JBIn0ATJyd9Bg=";
};

yarnBuildScript = "build:deployment";

nativeBuildInputs = [
yarnConfigHook
yarnBuildHook
nodejs
];

installPhase = ''
runHook preInstall

cp -r dist $out

runHook postInstall
'';

meta = meta // {
description = "Frontend for the federated audio platform, Funkwhale";
};
};

updateScript = nix-update-script {
extraArgs = [
"--subpackage"
"frontend"
];
};

inherit meta;
};
}
53 changes: 53 additions & 0 deletions pkgs/by-name/funkwhale/replace-unicode-slugify.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
diff --git a/funkwhale_api/common/storage.py b/funkwhale_api/common/storage.py
index ebf70a367..e5edfafae 100644
--- a/funkwhale_api/common/storage.py
+++ b/funkwhale_api/common/storage.py
@@ -1,4 +1,5 @@
import os
+import re
import shutil

import slugify
@@ -10,7 +11,7 @@ def asciionly(name):
"""
Convert unicode characters in name to ASCII characters.
"""
- return slugify.slugify(name, ok=slugify.SLUG_OK + ".", only_ascii=True)
+ return re.sub(r"[\s]+", "-", slugify.slugify(name, regex_pattern=r"[^\s\-_~\.a-zA-Z0-9]+", separator=""))


class ASCIIFileSystemStorage(FileSystemStorage):
diff --git a/funkwhale_api/music/models.py b/funkwhale_api/music/models.py
index 005990995..536e1dfdb 100644
--- a/funkwhale_api/music/models.py
+++ b/funkwhale_api/music/models.py
@@ -2,6 +2,7 @@ import datetime
import itertools
import logging
import os
+import re
import tempfile
import urllib.parse
import uuid
@@ -789,7 +790,7 @@ TRACK_FILE_IMPORT_STATUS_CHOICES = (

def get_file_path(instance, filename):
# Convert unicode characters in name to ASCII characters.
- filename = slugify.slugify(filename, ok=slugify.SLUG_OK + ".", only_ascii=True)
+ filename = re.sub(r"[\s]+", "-", slugify.slugify(filename, regex_pattern=r"[^\s\-_~\.a-zA-Z0-9]+", separator=""))

if isinstance(instance, UploadVersion):
return common_utils.ChunkedPath("transcoded")(instance, filename)
diff --git a/pyproject.toml b/pyproject.toml
index 23453fe10..ad8bb069e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -98,7 +98,7 @@ typesense = { version = "==1.0.3", optional = true }
ipython = "==9.2.0"
pluralizer = "==1.2.0"
service-identity = "==24.2.0"
-unicode-slugify = "==0.1.5"
+python-slugify = "==8.0.4"

[tool.poetry.group.dev.dependencies]
aioresponses = "==0.7.8"
Loading