mirror of
https://github.com/etesync/server
synced 2024-11-22 00:38:07 +00:00
Incoming invitations: implement incoming invitations and accepting them
This commit is contained in:
parent
8d1c02dcb9
commit
47e1eec122
@ -150,6 +150,7 @@ class CollectionInvitation(models.Model):
|
||||
version = models.PositiveSmallIntegerField(default=1)
|
||||
fromMember = models.ForeignKey(CollectionMember, on_delete=models.CASCADE)
|
||||
# FIXME: make sure to delete all invitations for the same collection once one is accepted
|
||||
# Make sure to not allow invitations if already a member
|
||||
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='incoming_invitations', on_delete=models.CASCADE)
|
||||
signedEncryptionKey = models.BinaryField(editable=False, blank=False, null=False)
|
||||
@ -165,6 +166,10 @@ class CollectionInvitation(models.Model):
|
||||
def __str__(self):
|
||||
return '{} {}'.format(self.fromMember.collection.uid, self.user)
|
||||
|
||||
@cached_property
|
||||
def collection(self):
|
||||
return self.fromMember.collection
|
||||
|
||||
|
||||
class UserInfo(models.Model):
|
||||
owner = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, primary_key=True)
|
||||
|
@ -268,18 +268,20 @@ class CollectionInvitationSerializer(serializers.ModelSerializer):
|
||||
slug_field=User.USERNAME_FIELD,
|
||||
queryset=User.objects
|
||||
)
|
||||
collection = serializers.SlugRelatedField(
|
||||
source='fromMember__collection',
|
||||
slug_field='uid',
|
||||
read_only=True,
|
||||
)
|
||||
fromPubkey = BinaryBase64Field(source='fromMember__user__userinfo__pubkey', read_only=True)
|
||||
collection = serializers.SerializerMethodField('get_collection')
|
||||
fromPubkey = serializers.SerializerMethodField('get_from_pubkey')
|
||||
signedEncryptionKey = BinaryBase64Field()
|
||||
|
||||
class Meta:
|
||||
model = models.CollectionInvitation
|
||||
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 create(self, validated_data):
|
||||
collection = self.context['collection']
|
||||
request = self.context['request']
|
||||
@ -301,6 +303,30 @@ class CollectionInvitationSerializer(serializers.ModelSerializer):
|
||||
return instance
|
||||
|
||||
|
||||
class InvitationAcceptSerializer(serializers.Serializer):
|
||||
encryptionKey = BinaryBase64Field()
|
||||
|
||||
def create(self, validated_data):
|
||||
|
||||
with transaction.atomic():
|
||||
invitation = self.context['invitation']
|
||||
encryption_key = validated_data.get('encryptionKey')
|
||||
|
||||
member = models.CollectionMember.objects.create(
|
||||
collection=invitation.collection,
|
||||
user=invitation.user,
|
||||
accessLevel=invitation.accessLevel,
|
||||
encryptionKey=encryption_key,
|
||||
)
|
||||
|
||||
invitation.delete()
|
||||
|
||||
return member
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class UserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = User
|
||||
|
@ -49,6 +49,7 @@ from .serializers import (
|
||||
CollectionItemChunkSerializer,
|
||||
CollectionMemberSerializer,
|
||||
CollectionInvitationSerializer,
|
||||
InvitationAcceptSerializer,
|
||||
UserSerializer,
|
||||
)
|
||||
|
||||
@ -456,6 +457,31 @@ class CollectionInvitationViewSet(BaseViewSet):
|
||||
return queryset.filter(fromMember__collection=collection)
|
||||
|
||||
|
||||
class InvitationIncomingViewSet(BaseViewSet):
|
||||
allowed_methods = ['GET', 'DELETE']
|
||||
queryset = CollectionInvitation.objects.all()
|
||||
serializer_class = CollectionInvitationSerializer
|
||||
lookup_field = 'uid'
|
||||
lookup_url_kwarg = 'invitation_uid'
|
||||
|
||||
def get_queryset(self, queryset=None):
|
||||
if queryset is None:
|
||||
queryset = type(self).queryset
|
||||
|
||||
return queryset.filter(user=self.request.user)
|
||||
|
||||
@action_decorator(detail=True, allowed_methods=['POST'], methods=['POST'])
|
||||
def accept(self, request, invitation_uid=None):
|
||||
invitation = get_object_or_404(self.get_queryset(), uid=invitation_uid)
|
||||
context = self.get_serializer_context()
|
||||
context.update({'invitation': invitation})
|
||||
|
||||
serializer = InvitationAcceptSerializer(data=request.data, context=context)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
serializer.save()
|
||||
return Response(status=status.HTTP_201_CREATED)
|
||||
|
||||
|
||||
class AuthenticationViewSet(viewsets.ViewSet):
|
||||
allowed_methods = ['POST']
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user