Skip to content

Commit

Permalink
Merge pull request #86 from bpepple/add-post-api-method
Browse files Browse the repository at this point in the history
post api changes
  • Loading branch information
bpepple authored Jan 6, 2022
2 parents 8b2cc66 + cce68f0 commit 522c485
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 10 deletions.
46 changes: 46 additions & 0 deletions comicsdb/permission.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
from django.contrib.auth.models import Group
from rest_framework import permissions


def _is_in_group(user, group_name):
"""
Takes a user and a group name, and returns `True` if the user is in that group.
"""
try:
return Group.objects.get(name=group_name).user_set.filter(id=user.id).exists()
except Group.DoesNotExist:
return None


def _has_group_permission(user, required_groups):
return any(_is_in_group(user, group_name) for group_name in required_groups)


class IsLoggedInUserOrEditor(permissions.BasePermission):
required_groups = ["editor"]

def has_object_permission(self, request, view, obj):
has_group_permission = _has_group_permission(request.user, self.required_groups)
if self.required_groups is None:
return False
return obj == request.user or has_group_permission


class IsEditor(permissions.BasePermission):
required_groups = ["editor"]

def has_permission(self, request, view):
has_group_permission = _has_group_permission(request.user, self.required_groups)
return request.user and has_group_permission

def has_object_permission(self, request, view, obj):
has_group_permission = _has_group_permission(request.user, self.required_groups)
return request.user and has_group_permission


class IsEditorOrContributor(permissions.BasePermission):
required_groups = ["editor", "contributor"]

def has_permission(self, request, view):
has_group_permission = _has_group_permission(request.user, self.required_groups)
return request.user and has_group_permission
41 changes: 39 additions & 2 deletions comicsdb/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,25 @@ class Meta:
class ArcSerializer(serializers.ModelSerializer):
class Meta:
model = Arc
fields = ("id", "name", "desc", "image", "modified")
fields = ("id", "name", "desc", "modified")
read_only_field = ("image",)

# TODO: Need to handle uploading of ImageField.

def create(self, validated_data):
"""
Create and return a new `Arc` instance, given the validated data.
"""
return Arc.objects.create(**validated_data)

def update(self, instance, validated_data):
"""
Update and return an existing `Arc` instance, given the validated data.
"""
instance.name = validated_data.get("name", instance.name)
instance.desc = validated_data.get("desc", instance.desc)
instance.save()
return instance


class CharacterSerializer(serializers.ModelSerializer):
Expand All @@ -99,11 +117,30 @@ class Meta:
"alias",
"desc",
"wikipedia",
"image",
"creators",
"teams",
"modified",
)
read_only_field = ("image",)

# TODO: Need to handle uploading of ImageField.

def create(self, validated_data):
"""
Create and return a new `Character` instance, given the validated data.
"""
return Character.objects.create(**validated_data)

def update(self, instance, validated_data):
"""
Update and return an existing `Character` instance, given the validated data.
"""
instance.name = validated_data.get("name", instance.name)
instance.alias = validated_data.get("alias", instance.alias)
instance.desc = validated_data.get("desc", instance.desc)
instance.wikipedia = validated_data.get("wikipedia", instance.wikipedia)
instance.save()
return instance


class CreatorSerializer(serializers.ModelSerializer):
Expand Down
29 changes: 21 additions & 8 deletions comicsdb/views/viewsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from comicsdb.filters.issue import IssueFilter
from comicsdb.filters.name import NameFilter
from comicsdb.filters.series import SeriesFilter
from comicsdb.permission import IsEditor, IsEditorOrContributor
from comicsdb.models import (
Arc,
Character,
Expand Down Expand Up @@ -37,7 +38,7 @@
)


class ArcViewSet(viewsets.ReadOnlyModelViewSet):
class ArcViewSet(viewsets.ModelViewSet):
"""
list:
Returns a list of all the story arcs.
Expand All @@ -53,9 +54,15 @@ class ArcViewSet(viewsets.ReadOnlyModelViewSet):
def get_serializer_class(self):
if self.action == "list":
return ArcListSerializer
if self.action == "retrieve":
return ArcSerializer
return ArcListSerializer
return ArcSerializer

def get_permissions(self):
permission_classes = []
if self.action in ["create", "update", "partial_update", "destroy"]:
permission_classes = [IsEditor]
elif self.action in ["retrieve", "list"]:
permission_classes = [IsEditorOrContributor]
return [permission() for permission in permission_classes]

@action(detail=True)
def issue_list(self, request, pk=None):
Expand All @@ -74,7 +81,7 @@ def issue_list(self, request, pk=None):
raise Http404()


class CharacterViewSet(viewsets.ReadOnlyModelViewSet):
class CharacterViewSet(viewsets.ModelViewSet):
"""
list:
Return a list of all the characters.
Expand All @@ -90,9 +97,15 @@ class CharacterViewSet(viewsets.ReadOnlyModelViewSet):
def get_serializer_class(self):
if self.action == "list":
return CharacterListSerializer
if self.action == "retrieve":
return CharacterSerializer
return CharacterListSerializer
return CharacterSerializer

def get_permissions(self):
permission_classes = []
if self.action in ["create", "update", "partial_update", "destroy"]:
permission_classes = [IsEditor]
elif self.action in ["retrieve", "list"]:
permission_classes = [IsEditorOrContributor]
return [permission() for permission in permission_classes]


class CreatorViewSet(viewsets.ReadOnlyModelViewSet):
Expand Down
9 changes: 9 additions & 0 deletions users/tests/case_base.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.auth.models import Group, Permission
from django.test import TestCase

from users.models import CustomUser
Expand All @@ -10,6 +11,14 @@ def _create_user(cls):
user.set_password("1234")
user.save()

# TODO: Need to split the group bit out for better test coverage (post, delete, etc)
contributor_group = Group.objects.create(name="contributor")
permission_codename = ["view_arc"]
for permission in permission_codename:
perm = Permission.objects.filter(codename=permission).first()
contributor_group.permissions.add(perm)
user.groups.add(contributor_group)

return user

def _client_login(self):
Expand Down
6 changes: 6 additions & 0 deletions users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from django.contrib import messages
from django.contrib.auth import login, update_session_auth_hash
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.models import Group
from django.contrib.sites.shortcuts import get_current_site
from django.shortcuts import redirect, render
from django.template.loader import render_to_string
Expand Down Expand Up @@ -41,6 +42,11 @@ def activate(request, uidb64, token):
user.is_active = True
user.email_confirmed = True
user.save()

# Add the user to the contributor group.
contributor_group = Group.objects.get(name="contributor")
user.groups.add(contributor_group)

login(request, user)
# Send pushover notification tha user activated account
send_pushover(f"{user} activated their account on Metron.")
Expand Down

0 comments on commit 522c485

Please sign in to comment.