1
0
mirror of https://github.com/etesync/server synced 2024-11-22 16:58:08 +00:00

Add a viewset to control collection membership.

This commit is contained in:
Tom Hacohen 2020-05-20 13:48:46 +03:00
parent 4ca74bc69b
commit edd88427b0
3 changed files with 61 additions and 8 deletions

View File

@ -121,12 +121,13 @@ class RevisionChunkRelation(models.Model):
ordering = ('id', ) ordering = ('id', )
class CollectionMember(models.Model):
class AccessLevels(models.TextChoices): class AccessLevels(models.TextChoices):
ADMIN = 'adm' ADMIN = 'adm'
READ_WRITE = 'rw' READ_WRITE = 'rw'
READ_ONLY = 'ro' READ_ONLY = 'ro'
class CollectionMember(models.Model):
collection = models.ForeignKey(Collection, related_name='members', on_delete=models.CASCADE) collection = models.ForeignKey(Collection, related_name='members', on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
encryptionKey = models.BinaryField(editable=True, blank=False, null=False) encryptionKey = models.BinaryField(editable=True, blank=False, null=False)

View File

@ -211,7 +211,7 @@ class CollectionSerializer(serializers.ModelSerializer):
models.CollectionMember(collection=instance, models.CollectionMember(collection=instance,
user=validated_data.get('owner'), user=validated_data.get('owner'),
accessLevel=models.CollectionMember.AccessLevels.ADMIN, accessLevel=models.AccessLevels.ADMIN,
encryptionKey=encryption_key, encryptionKey=encryption_key,
).save() ).save()
@ -238,6 +238,30 @@ class CollectionSerializer(serializers.ModelSerializer):
return instance return instance
class CollectionMemberSerializer(serializers.ModelSerializer):
username = serializers.SlugRelatedField(
source='user',
slug_field=User.USERNAME_FIELD,
queryset=User.objects
)
encryptionKey = BinaryBase64Field()
class Meta:
model = models.CollectionMember
fields = ('username', 'encryptionKey', 'accessLevel')
def create(self, validated_data):
raise NotImplementedError()
def update(self, instance, validated_data):
with transaction.atomic():
# We only allow updating accessLevel
instance.accessLevel = validated_data.pop('accessLevel')
instance.save()
return instance
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User

View File

@ -33,8 +33,8 @@ import nacl.signing
import nacl.secret import nacl.secret
import nacl.hash import nacl.hash
from . import app_settings from . import app_settings, permissions
from .models import Collection, CollectionItem, CollectionItemRevision from .models import Collection, CollectionItem, CollectionItemRevision, CollectionMember
from .serializers import ( from .serializers import (
b64encode, b64encode,
AuthenticationSignupSerializer, AuthenticationSignupSerializer,
@ -47,6 +47,7 @@ from .serializers import (
CollectionItemDepSerializer, CollectionItemDepSerializer,
CollectionItemRevisionSerializer, CollectionItemRevisionSerializer,
CollectionItemChunkSerializer, CollectionItemChunkSerializer,
CollectionMemberSerializer,
UserSerializer, UserSerializer,
) )
@ -395,6 +396,33 @@ class CollectionItemChunkViewSet(viewsets.ViewSet):
return serve(request, basename, dirname) return serve(request, basename, dirname)
class CollectionMemberViewSet(BaseViewSet):
allowed_methods = ['GET', 'PUT', 'DELETE']
permission_classes = BaseViewSet.permission_classes + (permissions.IsCollectionAdmin, )
queryset = CollectionMember.objects.all()
serializer_class = CollectionMemberSerializer
lookup_field = 'user__' + User.USERNAME_FIELD
lookup_url_kwarg = 'username'
# FIXME: need to make sure that there's always an admin, and maybe also don't let an owner remove adm access
# (if we want to transfer, we need to do that specifically)
def get_queryset(self, queryset=None):
collection_uid = self.kwargs['collection_uid']
try:
collection = self.get_collection_queryset(Collection.objects).get(uid=collection_uid)
except Collection.DoesNotExist:
raise Http404('Collection does not exist')
if queryset is None:
queryset = type(self).queryset
return queryset.filter(collection=collection)
def create(self, request):
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
class AuthenticationViewSet(viewsets.ViewSet): class AuthenticationViewSet(viewsets.ViewSet):
allowed_methods = ['POST'] allowed_methods = ['POST']