See #212: API viewset
This commit is contained in:
parent
2e4f862387
commit
3ef5f29dd3
|
@ -3,6 +3,7 @@ from django_filters import rest_framework as filters
|
||||||
|
|
||||||
from funkwhale_api.common import fields
|
from funkwhale_api.common import fields
|
||||||
from funkwhale_api.music import models as music_models
|
from funkwhale_api.music import models as music_models
|
||||||
|
from funkwhale_api.users import models as users_models
|
||||||
|
|
||||||
|
|
||||||
class ManageTrackFileFilterSet(filters.FilterSet):
|
class ManageTrackFileFilterSet(filters.FilterSet):
|
||||||
|
@ -18,3 +19,21 @@ class ManageTrackFileFilterSet(filters.FilterSet):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = music_models.TrackFile
|
model = music_models.TrackFile
|
||||||
fields = ["q", "track__album", "track__artist", "track", "library_track"]
|
fields = ["q", "track__album", "track__artist", "track", "library_track"]
|
||||||
|
|
||||||
|
|
||||||
|
class ManageUserFilterSet(filters.FilterSet):
|
||||||
|
q = fields.SearchFilter(search_fields=["username", "email", "name"])
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = users_models.User
|
||||||
|
fields = [
|
||||||
|
"q",
|
||||||
|
"is_active",
|
||||||
|
"privacy_level",
|
||||||
|
"is_staff",
|
||||||
|
"is_superuser",
|
||||||
|
"permission_upload",
|
||||||
|
"permission_library",
|
||||||
|
"permission_settings",
|
||||||
|
"permission_federation",
|
||||||
|
]
|
||||||
|
|
|
@ -3,6 +3,7 @@ from rest_framework import serializers
|
||||||
|
|
||||||
from funkwhale_api.common import serializers as common_serializers
|
from funkwhale_api.common import serializers as common_serializers
|
||||||
from funkwhale_api.music import models as music_models
|
from funkwhale_api.music import models as music_models
|
||||||
|
from funkwhale_api.users import models as users_models
|
||||||
|
|
||||||
from . import filters
|
from . import filters
|
||||||
|
|
||||||
|
@ -67,3 +68,34 @@ class ManageTrackFileActionSerializer(common_serializers.ActionSerializer):
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def handle_delete(self, objects):
|
def handle_delete(self, objects):
|
||||||
return objects.delete()
|
return objects.delete()
|
||||||
|
|
||||||
|
|
||||||
|
class ManageUserSerializer(serializers.ModelSerializer):
|
||||||
|
permissions = serializers.SerializerMethodField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = users_models.User
|
||||||
|
fields = (
|
||||||
|
"id",
|
||||||
|
"username",
|
||||||
|
"email",
|
||||||
|
"name",
|
||||||
|
"is_active",
|
||||||
|
"is_staff",
|
||||||
|
"is_superuser",
|
||||||
|
"date_joined",
|
||||||
|
"last_activity",
|
||||||
|
"permissions",
|
||||||
|
"privacy_level",
|
||||||
|
)
|
||||||
|
read_only_fields = [
|
||||||
|
"id",
|
||||||
|
"email",
|
||||||
|
"privacy_level",
|
||||||
|
"username",
|
||||||
|
"date_joined",
|
||||||
|
"last_activity",
|
||||||
|
]
|
||||||
|
|
||||||
|
def get_permissions(self, o):
|
||||||
|
return o.get_permissions(defaults=self.context.get("default_permissions"))
|
||||||
|
|
|
@ -5,7 +5,10 @@ from . import views
|
||||||
|
|
||||||
library_router = routers.SimpleRouter()
|
library_router = routers.SimpleRouter()
|
||||||
library_router.register(r"track-files", views.ManageTrackFileViewSet, "track-files")
|
library_router.register(r"track-files", views.ManageTrackFileViewSet, "track-files")
|
||||||
|
users_router = routers.SimpleRouter()
|
||||||
|
users_router.register(r"users", views.ManageUserViewSet, "users")
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r"^library/", include((library_router.urls, "instance"), namespace="library"))
|
url(r"^library/", include((library_router.urls, "instance"), namespace="library")),
|
||||||
|
url(r"^users/", include((users_router.urls, "instance"), namespace="users")),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
from rest_framework import mixins, response, viewsets
|
from rest_framework import mixins, response, viewsets
|
||||||
from rest_framework.decorators import list_route
|
from rest_framework.decorators import list_route
|
||||||
|
|
||||||
|
from funkwhale_api.common import preferences
|
||||||
from funkwhale_api.music import models as music_models
|
from funkwhale_api.music import models as music_models
|
||||||
|
from funkwhale_api.users import models as users_models
|
||||||
from funkwhale_api.users.permissions import HasUserPermission
|
from funkwhale_api.users.permissions import HasUserPermission
|
||||||
|
|
||||||
from . import filters, serializers
|
from . import filters, serializers
|
||||||
|
@ -41,3 +43,22 @@ class ManageTrackFileViewSet(
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
result = serializer.save()
|
result = serializer.save()
|
||||||
return response.Response(result, status=200)
|
return response.Response(result, status=200)
|
||||||
|
|
||||||
|
|
||||||
|
class ManageUserViewSet(
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
|
mixins.UpdateModelMixin,
|
||||||
|
viewsets.GenericViewSet,
|
||||||
|
):
|
||||||
|
queryset = users_models.User.objects.all().order_by("-id")
|
||||||
|
serializer_class = serializers.ManageUserSerializer
|
||||||
|
filter_class = filters.ManageUserFilterSet
|
||||||
|
permission_classes = (HasUserPermission,)
|
||||||
|
required_permissions = ["settings"]
|
||||||
|
ordering_fields = ["date_joined", "last_activity", "username"]
|
||||||
|
|
||||||
|
def get_serializer_context(self):
|
||||||
|
context = super().get_serializer_context()
|
||||||
|
context["default_permissions"] = preferences.get("users__default_permissions")
|
||||||
|
return context
|
||||||
|
|
|
@ -82,8 +82,8 @@ class User(AbstractUser):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.username
|
return self.username
|
||||||
|
|
||||||
def get_permissions(self):
|
def get_permissions(self, defaults=None):
|
||||||
defaults = preferences.get("users__default_permissions")
|
defaults = defaults or preferences.get("users__default_permissions")
|
||||||
perms = {}
|
perms = {}
|
||||||
for p in PERMISSIONS:
|
for p in PERMISSIONS:
|
||||||
v = (
|
v = (
|
||||||
|
|
|
@ -5,7 +5,11 @@ from funkwhale_api.manage import serializers, views
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"view,permissions,operator", [(views.ManageTrackFileViewSet, ["library"], "and")]
|
"view,permissions,operator",
|
||||||
|
[
|
||||||
|
(views.ManageTrackFileViewSet, ["library"], "and"),
|
||||||
|
(views.ManageUserViewSet, ["settings"], "and"),
|
||||||
|
],
|
||||||
)
|
)
|
||||||
def test_permissions(assert_user_permission, view, permissions, operator):
|
def test_permissions(assert_user_permission, view, permissions, operator):
|
||||||
assert_user_permission(view, permissions, operator)
|
assert_user_permission(view, permissions, operator)
|
||||||
|
@ -23,3 +27,18 @@ def test_track_file_view(factories, superuser_api_client):
|
||||||
|
|
||||||
assert response.data["count"] == len(tfs)
|
assert response.data["count"] == len(tfs)
|
||||||
assert response.data["results"] == expected
|
assert response.data["results"] == expected
|
||||||
|
|
||||||
|
|
||||||
|
def test_user_view(factories, superuser_api_client, mocker):
|
||||||
|
mocker.patch("funkwhale_api.users.models.User.record_activity")
|
||||||
|
users = factories["users.User"].create_batch(size=5) + [superuser_api_client.user]
|
||||||
|
qs = users[0].__class__.objects.order_by("-id")
|
||||||
|
url = reverse("api:v1:manage:users:users-list")
|
||||||
|
|
||||||
|
response = superuser_api_client.get(url, {"sort": "-id"})
|
||||||
|
expected = serializers.ManageUserSerializer(
|
||||||
|
qs, many=True, context={"request": response.wsgi_request}
|
||||||
|
).data
|
||||||
|
|
||||||
|
assert response.data["count"] == len(users)
|
||||||
|
assert response.data["results"] == expected
|
||||||
|
|
Loading…
Reference in New Issue