Invitation: move outgoing invitations to invite/outgoing.

This commit is contained in:
Tom Hacohen 2020-05-24 18:19:22 +03:00
parent 118dbea4e3
commit a965a76c36
3 changed files with 36 additions and 29 deletions

View File

@ -16,6 +16,11 @@ from rest_framework import permissions
from django_etesync.models import Collection, AccessLevels from django_etesync.models import Collection, AccessLevels
def is_collection_admin(collection, user):
member = collection.members.filter(user=user).first()
return (member is not None) and (member.accessLevel == AccessLevels.ADMIN)
class IsCollectionAdmin(permissions.BasePermission): class IsCollectionAdmin(permissions.BasePermission):
""" """
Custom permission to only allow owners of a collection to view it Custom permission to only allow owners of a collection to view it
@ -27,8 +32,7 @@ class IsCollectionAdmin(permissions.BasePermission):
collection_uid = view.kwargs['collection_uid'] collection_uid = view.kwargs['collection_uid']
try: try:
collection = view.get_collection_queryset().get(uid=collection_uid) collection = view.get_collection_queryset().get(uid=collection_uid)
member = collection.members.filter(user=request.user).first() return is_collection_admin(collection, request.user)
return (member is not None) and (member.accessLevel == AccessLevels.ADMIN)
except Collection.DoesNotExist: except Collection.DoesNotExist:
# If the collection does not exist, we want to 404 later, not permission denied. # If the collection does not exist, we want to 404 later, not permission denied.
return True return True

View File

@ -268,29 +268,24 @@ class CollectionInvitationSerializer(serializers.ModelSerializer):
slug_field=User.USERNAME_FIELD, slug_field=User.USERNAME_FIELD,
queryset=User.objects queryset=User.objects
) )
collection = serializers.SerializerMethodField('get_collection') collection = serializers.CharField(source='collection.uid')
fromPubkey = serializers.SerializerMethodField('get_from_pubkey') fromPubkey = BinaryBase64Field(source='fromMember.user.userinfo.pubkey', read_only=True)
signedEncryptionKey = BinaryBase64Field() signedEncryptionKey = BinaryBase64Field()
class Meta: class Meta:
model = models.CollectionInvitation model = models.CollectionInvitation
fields = ('username', 'uid', 'collection', 'signedEncryptionKey', 'accessLevel', 'fromPubkey', 'version') fields = ('username', 'uid', 'collection', 'signedEncryptionKey', 'accessLevel', 'fromPubkey', 'version')
def get_collection(self, obj):
return obj.collection.uid
def get_from_pubkey(self, obj):
return b64encode(obj.fromMember.user.userinfo.pubkey)
def validate_user(self, value): def validate_user(self, value):
request = self.context['request'] request = self.context['request']
if request.user == value: if request.user == value.lower():
raise serializers.ValidationError('Inviting yourself is not allowed') raise serializers.ValidationError('Inviting yourself is not allowed')
return value
def create(self, validated_data): def create(self, validated_data):
collection = self.context['collection']
request = self.context['request'] request = self.context['request']
collection = validated_data.pop('collection')
member = collection.members.get(user=request.user) member = collection.members.get(user=request.user)

View File

@ -16,6 +16,7 @@ import json
from django.conf import settings from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from django.db import transaction, IntegrityError from django.db import transaction, IntegrityError
from django.db.models import Max from django.db.models import Max
from django.http import HttpResponseBadRequest, HttpResponse, Http404 from django.http import HttpResponseBadRequest, HttpResponse, Http404
@ -426,9 +427,9 @@ class CollectionMemberViewSet(BaseViewSet):
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
class CollectionInvitationViewSet(BaseViewSet): class InvitationOutgoingViewSet(BaseViewSet):
allowed_methods = ['GET', 'POST', 'PUT', 'DELETE'] allowed_methods = ['GET', 'POST', 'PUT', 'DELETE']
permission_classes = BaseViewSet.permission_classes + (permissions.IsCollectionAdmin, ) permission_classes = BaseViewSet.permission_classes
queryset = CollectionInvitation.objects.all() queryset = CollectionInvitation.objects.all()
serializer_class = CollectionInvitationSerializer serializer_class = CollectionInvitationSerializer
lookup_field = 'uid' lookup_field = 'uid'
@ -436,29 +437,36 @@ class CollectionInvitationViewSet(BaseViewSet):
def get_serializer_context(self): def get_serializer_context(self):
context = super().get_serializer_context() context = super().get_serializer_context()
collection_uid = self.kwargs['collection_uid'] context.update({'request': self.request})
try:
collection = self.get_collection_queryset(Collection.objects).get(uid=collection_uid)
except Collection.DoesNotExist:
raise Http404('Collection does not exist')
context.update({'request': self.request, 'collection': collection})
return context return context
def get_queryset(self, queryset=None): def get_queryset(self, queryset=None):
collection_uid = self.kwargs['collection_uid'] if queryset is None:
queryset = type(self).queryset
return queryset.filter(fromMember__user=self.request.user)
def create(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data, context=self.get_serializer_context())
if serializer.is_valid():
collection_uid = serializer.validated_data.get('collection', {}).get('uid')
try: try:
collection = self.get_collection_queryset(Collection.objects).get(uid=collection_uid) collection = self.get_collection_queryset(Collection.objects).get(uid=collection_uid)
except Collection.DoesNotExist: except Collection.DoesNotExist:
raise Http404('Collection does not exist') raise Http404('Collection does not exist')
if queryset is None: if not permissions.is_collection_admin(collection, request.user):
queryset = type(self).queryset raise PermissionDenied('User is not an admin of this collection')
return queryset.filter(fromMember__collection=collection) serializer.save(collection=collection)
return Response({}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@action_decorator(detail=False, allowed_methods=['GET'], methods=['GET']) @action_decorator(detail=False, allowed_methods=['GET'], methods=['GET'])
def fetch_user_profile(self, request, collection_uid=None): def fetch_user_profile(self, request):
username = request.GET.get('username') username = request.GET.get('username')
kwargs = {'owner__' + User.USERNAME_FIELD: username} kwargs = {'owner__' + User.USERNAME_FIELD: username}
user_info = get_object_or_404(UserInfo.objects.all(), **kwargs) user_info = get_object_or_404(UserInfo.objects.all(), **kwargs)