1
0
mirror of https://github.com/etesync/server synced 2024-11-26 02:38:15 +00:00

More progress.

This commit is contained in:
Tom Hacohen 2020-02-20 13:56:16 +02:00
parent 4075f775e7
commit 67fb714ddb
6 changed files with 197 additions and 27 deletions

View File

@ -0,0 +1,29 @@
# Generated by Django 3.0.3 on 2020-02-20 11:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('django_etesync', '0004_auto_20200220_1029'),
]
operations = [
migrations.RemoveField(
model_name='collectionitemchunk',
name='items',
),
migrations.AddField(
model_name='collectionitem',
name='chunks',
field=models.ManyToManyField(related_name='items', to='django_etesync.CollectionItemChunk'),
),
migrations.AddField(
model_name='collectionitemchunk',
name='collection',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='chunks', to='django_etesync.Collection'),
preserve_default=False,
),
]

View File

@ -0,0 +1,49 @@
# Generated by Django 3.0.3 on 2020-02-20 11:37
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('django_etesync', '0005_auto_20200220_1123'),
]
operations = [
migrations.RemoveField(
model_name='collectionitem',
name='chunks',
),
migrations.RemoveField(
model_name='collectionitem',
name='current',
),
migrations.RemoveField(
model_name='collectionitem',
name='encryptionKey',
),
migrations.RemoveField(
model_name='collectionitem',
name='hmac',
),
migrations.RemoveField(
model_name='collectionitem',
name='version',
),
migrations.CreateModel(
name='CollectionItemSnapshot',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('version', models.PositiveSmallIntegerField()),
('encryptionKey', models.BinaryField(editable=True)),
('hmac', models.CharField(max_length=50)),
('current', models.BooleanField(db_index=True, default=True)),
('chunks', models.ManyToManyField(related_name='items', to='django_etesync.CollectionItemChunk')),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='snapshots', to='django_etesync.CollectionItem')),
],
options={
'unique_together': {('item', 'current')},
},
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 3.0.3 on 2020-02-20 11:44
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('django_etesync', '0006_auto_20200220_1137'),
]
operations = [
migrations.AddField(
model_name='collectionitemchunk',
name='item',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='chunks', to='django_etesync.CollectionItem'),
preserve_default=False,
),
migrations.AlterUniqueTogether(
name='collectionitemchunk',
unique_together={('item', 'order')},
),
migrations.RemoveField(
model_name='collectionitemchunk',
name='collection',
),
]

View File

@ -35,26 +35,6 @@ class Collection(models.Model):
def __str__(self): def __str__(self):
return self.uid return self.uid
@cached_property
def current_items(self):
return self.items.filter(current=True)
class CollectionItem(models.Model):
uid = models.CharField(db_index=True, blank=False, null=False,
max_length=44, validators=[UidValidator])
version = models.PositiveSmallIntegerField()
encryptionKey = models.BinaryField(editable=True, blank=False, null=False)
collection = models.ForeignKey(Collection, related_name='items', on_delete=models.CASCADE)
hmac = models.CharField(max_length=50, blank=False, null=False)
current = models.BooleanField(db_index=True, default=True)
class Meta:
unique_together = ('uid', 'collection')
def __str__(self):
return self.uid
def chunk_directory_path(instance, filename): def chunk_directory_path(instance, filename):
col = instance.itemSnapshot.item.collection col = instance.itemSnapshot.item.collection
@ -62,15 +42,49 @@ def chunk_directory_path(instance, filename):
return Path('user_{}'.format(user_id), col.uid, instance.uid) return Path('user_{}'.format(user_id), col.uid, instance.uid)
class CollectionItem(models.Model):
uid = models.CharField(db_index=True, blank=False, null=False,
max_length=44, validators=[UidValidator])
collection = models.ForeignKey(Collection, related_name='items', on_delete=models.CASCADE)
class Meta:
unique_together = ('uid', 'collection')
def __str__(self):
return self.uid
@cached_property
def content(self):
return self.snapshots.get(current=True)
class CollectionItemChunk(models.Model): class CollectionItemChunk(models.Model):
uid = models.CharField(db_index=True, blank=False, null=False, uid = models.CharField(db_index=True, blank=False, null=False,
max_length=44, validators=[UidValidator]) max_length=44, validators=[UidValidator])
items = models.ManyToManyField(CollectionItem, related_name='chunks') item = models.ForeignKey(CollectionItem, related_name='chunks', on_delete=models.CASCADE)
order = models.CharField(max_length=100, blank=False, null=False) order = models.CharField(max_length=100, blank=False, null=False)
# We probably just want to implement this manually because we can have more than one pointing to a file. chunkFile = models.FileField(upload_to=chunk_directory_path) # We probably just want to implement this manually because we can have more than one pointing to a file. chunkFile = models.FileField(upload_to=chunk_directory_path)
class Meta: class Meta:
unique_together = ('item', 'order')
ordering = ['order'] ordering = ['order']
def __str__(self): def __str__(self):
return self.uid return self.uid
class CollectionItemSnapshot(models.Model):
version = models.PositiveSmallIntegerField()
encryptionKey = models.BinaryField(editable=True, blank=False, null=False)
item = models.ForeignKey(CollectionItem, related_name='snapshots', on_delete=models.CASCADE)
chunks = models.ManyToManyField(CollectionItemChunk, related_name='items')
hmac = models.CharField(max_length=50, blank=False, null=False)
current = models.BooleanField(db_index=True, default=True)
class Meta:
unique_together = ('item', 'current')
def __str__(self):
return '{} {} current={}'.format(self.item.uid, self.id, self.current)

View File

@ -64,7 +64,7 @@ class CollectionItemChunkSerializer(serializers.ModelSerializer):
fields = ('uid', ) fields = ('uid', )
class CollectionItemSerializer(serializers.ModelSerializer): class CollectionItemSnapshotSerializer(serializers.ModelSerializer):
encryptionKey = BinaryBase64Field() encryptionKey = BinaryBase64Field()
chunks = serializers.SlugRelatedField( chunks = serializers.SlugRelatedField(
slug_field='uid', slug_field='uid',
@ -73,18 +73,30 @@ class CollectionItemSerializer(serializers.ModelSerializer):
) )
class Meta: class Meta:
model = models.CollectionItem model = models.CollectionItemSnapshot
fields = ('uid', 'version', 'encryptionKey', 'chunks', 'hmac') fields = ('version', 'encryptionKey', 'chunks', 'hmac')
class CollectionItemInlineSerializer(CollectionItemSerializer): class CollectionItemSnapshotInlineSerializer(CollectionItemSnapshotSerializer):
chunksData = serializers.SerializerMethodField('get_inline_chunks_from_context') chunksData = serializers.SerializerMethodField('get_inline_chunks_from_context')
class Meta(CollectionItemSerializer.Meta): class Meta(CollectionItemSnapshotSerializer.Meta):
fields = CollectionItemSerializer.Meta.fields + ('chunksData', ) fields = CollectionItemSnapshotSerializer.Meta.fields + ('chunksData', )
def get_inline_chunks_from_context(self, obj): def get_inline_chunks_from_context(self, obj):
request = self.context.get('request', None) request = self.context.get('request', None)
if request is not None: if request is not None:
return ['SomeInlineData', 'Somemoredata'] return ['SomeInlineData', 'Somemoredata']
return 'readOnly' return 'readOnly'
class CollectionItemSerializer(serializers.ModelSerializer):
content = CollectionItemSnapshotSerializer(read_only=True, many=False)
class Meta:
model = models.CollectionItem
fields = ('uid', 'content')
class CollectionItemInlineSerializer(CollectionItemSerializer):
content = CollectionItemSnapshotInlineSerializer(read_only=True, many=False)

View File

@ -24,6 +24,7 @@ from django.views.decorators.http import require_POST
from rest_framework import status from rest_framework import status
from rest_framework import viewsets from rest_framework import viewsets
from rest_framework import parsers
from rest_framework.response import Response from rest_framework.response import Response
from . import app_settings, paginators from . import app_settings, paginators
@ -143,3 +144,40 @@ class CollectionItemViewSet(BaseViewSet):
def partial_update(self, request, collection_uid=None, uid=None): def partial_update(self, request, collection_uid=None, uid=None):
# FIXME: implement, or should it be implemented elsewhere? # FIXME: implement, or should it be implemented elsewhere?
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
class CollectionItemChunkViewSet(viewsets.ViewSet):
allowed_methods = ['GET', 'POST']
authentication_classes = BaseViewSet.authentication_classes
permission_classes = BaseViewSet.permission_classes
parser_classes = (parsers.MultiPartParser, )
lookup_field = 'uid'
def create(self, request, collection_uid=None):
# FIXME: we are potentially not getting the correct queryset
collection_object = Collection.objects.get(uid=collection_uid)
many = isinstance(request.data, list)
serializer = self.serializer_class(data=request.data, many=many)
if serializer.is_valid():
try:
serializer.save(collection=collection_object)
except IntegrityError:
content = {'code': 'integrity_error'}
return Response(content, status=status.HTTP_400_BAD_REQUEST)
return Response({}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def destroy(self, request, collection_uid=None, uid=None):
# FIXME: implement
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def update(self, request, collection_uid=None, uid=None):
# FIXME: implement, or should it be implemented elsewhere?
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
def partial_update(self, request, collection_uid=None, uid=None):
# FIXME: implement, or should it be implemented elsewhere?
return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)