UserServerLink model

This commit is contained in:
Corban-Lee Jones 2024-03-20 13:47:12 +00:00
parent e3484a9f21
commit 8952fdcd98
6 changed files with 152 additions and 26 deletions

View File

@ -5,6 +5,7 @@ import logging
from rest_framework import serializers
from apps.home.models import Subscription, TrackedContent
from apps.authentication.models import UserServerLink
log = logging.getLogger(__name__)
@ -128,6 +129,7 @@ class SubscriptionSerializer(DynamicModelSerializer):
model = Subscription
fields = ("uuid", "name", "rss_url", "image", "server", "targets", "creation_datetime", "extra_notes", "active")
class TrackedContentSerializer(DynamicModelSerializer):
"""
Serializer for the TrackedContent Model.
@ -136,3 +138,13 @@ class TrackedContentSerializer(DynamicModelSerializer):
class Meta:
model = TrackedContent
fields = ("uuid", "content_url", "subscription", "creation_datetime")
class UserServerLinkSerializer(DynamicModelSerializer):
"""
Serializer for the UserServerLink Model.
"""
class Meta:
model = UserServerLink
fields = ("id", "server_id", "user", "name", "permissions")

View File

@ -7,7 +7,9 @@ from .views import (
Subscription_ListView,
Subscription_DetailView,
TrackedContent_ListView,
TrackedContent_DetailView
TrackedContent_DetailView,
UserServerLink_ListView,
UserServerLink_DetailView
)
@ -23,5 +25,10 @@ urlpatterns = [
path("tracked/", include([
path("", TrackedContent_ListView.as_view(), name="tracked"),
path("<str:pk>/", TrackedContent_DetailView.as_view(), name="tracked-detail")
]))
])),
path("serverlink/", include([
path("", UserServerLink_ListView.as_view(), name="serverlink"),
path("<int:pk>/", UserServerLink_DetailView.as_view(), name="serverlink-detail")
])),
]

View File

@ -1,5 +1,7 @@
# -*- encoding: utf-8 -*-
import logging
from django.db.utils import IntegrityError
from django.core.exceptions import ValidationError
from django_filters import rest_framework as rest_filters
@ -10,10 +12,14 @@ from rest_framework.authentication import SessionAuthentication, TokenAuthentica
from rest_framework.parsers import MultiPartParser, FormParser
from apps.home.models import Subscription, TrackedContent
from apps.authentication.models import UserServerLink
from .serializers import (
SubscriptionSerializer,
TrackedContentSerializer
)
TrackedContentSerializer,
UserServerLinkSerializer
)
log = logging.getLogger(__name__)
class DefaultPagination(PageNumberPagination):
@ -68,7 +74,7 @@ class Subscription_DetailView(generics.RetrieveUpdateDestroyAPIView):
"""
View to provide details on a particular Subscription model instances.
Supports: GET, DELETE
Supports: GET, PUT, PATCH, DELETE
"""
authentication_classes = [SessionAuthentication, TokenAuthentication]
@ -76,14 +82,14 @@ class Subscription_DetailView(generics.RetrieveUpdateDestroyAPIView):
parser_classes = [MultiPartParser, FormParser]
serializer_class = SubscriptionSerializer
# queryset = Subscription.objects.all().order_by("-creation_datetime")
queryset = Subscription.objects.all().order_by("-creation_datetime")
def get_queryset(self):
user_servers = self.request.user.servers
user_servers = [server.id for server in user_servers]
return Subscription.objects \
.filter(server__in=user_servers) \
.order_by("-creation_datetime")
# def get_queryset(self):
# user_servers = self.request.user.servers
# user_servers = [server.id for server in user_servers]
# return Subscription.objects \
# .filter(server__in=user_servers) \
# .order_by("-creation_datetime")
# =================================================================================================
@ -139,3 +145,82 @@ class TrackedContent_DetailView(generics.RetrieveDestroyAPIView):
serializer_class = TrackedContentSerializer
queryset = TrackedContent.objects.all().order_by("-creation_datetime")
# =================================================================================================
# UserServerLinks Views
class UserServerLink_Pagination(PageNumberPagination):
"""
Pagination for UserServerLink API views.
Set to 200 as a discord user cannot exceed membership of
200 discord servers.
"""
page_size = 200
page_size_query_param = "page_size"
max_page_size = 200
class UserServerLink_MembershipPermission(permissions.BasePermission):
"""
Permission for UserServerLink that requires the current user
to be equal to the object.user.
"""
def has_object_permission(self, request, view, obj):
log.debug(f"{obj.name} {obj.user} {request.user}")
return obj.user == request.user
class UserServerLink_ListView(generics.ListCreateAPIView):
"""
View to provide a list of UserServerLink model instances.
Can also be used to create a new instance.
Supports: GET, POST
"""
authentication_classes = [SessionAuthentication, TokenAuthentication]
permission_classes = [permissions.IsAuthenticated, UserServerLink_MembershipPermission]
pagination_class = UserServerLink_Pagination
serializer_class = UserServerLinkSerializer
filter_backends = [filters.SearchFilter, rest_filters.DjangoFilterBackend, filters.OrderingFilter]
filterset_fields = ["id", "server_id", "user", "name", "permissions"]
search_fields = ["name"]
def get_queryset(self):
return UserServerLink.objects.filter(user=self.request.user).order_by("id")
def post(self, request):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
try:
self.perform_create(serializer)
except IntegrityError:
return Response(
{"detail": "UserServerLinks must be unique"},
status=status.HTTP_409_CONFLICT,
exception=True
)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
class UserServerLink_DetailView(generics.RetrieveDestroyAPIView):
"""
View to provide details on a particular UserServerLink model instances.
Supports: GET, DELETE
"""
authentication_classes = [SessionAuthentication, TokenAuthentication]
permission_classes = [permissions.IsAuthenticated, UserServerLink_MembershipPermission]
parser_classes = [MultiPartParser, FormParser]
serializer_class = UserServerLinkSerializer
queryset = UserServerLink.objects.all()

View File

@ -2,11 +2,16 @@
from django.contrib import admin
from .models import DiscordUser
from .models import DiscordUser, UserServerLink
@admin.register
@admin.register(DiscordUser)
class DiscordUserAdmin(admin.ModelAdmin):
list_display = ["id", "username", "global_name", "last_login", "is_staff", "is_superuser", "is_staff"]
list_filter = ["is_staff", "is_superuser", "is_active"]
@admin.register(UserServerLink)
class UserServerLink(admin.ModelAdmin):
list_display = ["id", "user", "name", "permissions"]

View File

@ -131,10 +131,10 @@ class UserServerLink(models.Model):
user only interacts with Subscriptions for their servers.
"""
id = models.PositiveBigIntegerField(primary_key=True)
user_id = models.ForeignKey(to=DiscordUser, on_delete=models.CASCADE)
server_id = models.PositiveBigIntegerField()
user = models.ForeignKey(to=DiscordUser, on_delete=models.CASCADE)
name = models.CharField(max_length=64)
perm_flags = models.IntegerField(null=True, blank=True)
permissions = models.IntegerField()
def __str__(self):
return self.name

View File

@ -1,5 +1,6 @@
# -*- encoding: utf-8 -*-
import json
import logging
import requests
@ -93,18 +94,34 @@ class GuildsView(View):
)
content = response.json()
servers = [UserServerLink(
id=server["id"],
user_id=request.user,
name=server["name"]
) for server in content]
UserServerLink.objects.filter(user_id=request.user).delete()
UserServerLink.objects.bulk_create(servers)
self.create_server_links(request.user, content)
return JsonResponse(content, safe=False)
def create_server_links(self, user, content: list[dict]):
"""
Creates objects representing the user's discord servers, storing
server info and the user's permissions within.
Parameters
----------
content : list[dict]
Raw data for the servers.
"""
servers = [
UserServerLink(
server_id=server["id"],
user=user,
name=server["name"],
permissions=server["permissions"]
)
for server in content
]
UserServerLink.objects.filter(user=user).delete()
UserServerLink.objects.bulk_create(servers)
class GuildChannelsView(View):