mirror of
https://github.com/etesync/server
synced 2024-11-25 18:28:46 +00:00
Collection: add content support.
This commit is contained in:
parent
c56cbb3f82
commit
66e5062461
19
django_etesync/migrations/0027_collection_mainitem.py
Normal file
19
django_etesync/migrations/0027_collection_mainitem.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-12 14:14
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_etesync', '0026_collectionitemrevision_meta'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='collection',
|
||||
name='mainItem',
|
||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='of_collection', to='django_etesync.CollectionItem'),
|
||||
),
|
||||
]
|
24
django_etesync/migrations/0028_auto_20200312_1819.py
Normal file
24
django_etesync/migrations/0028_auto_20200312_1819.py
Normal file
@ -0,0 +1,24 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-12 18:19
|
||||
|
||||
import django.core.validators
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_etesync', '0027_collection_mainitem'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='collectionitem',
|
||||
name='encryptionKey',
|
||||
field=models.BinaryField(editable=True, null=True),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='collectionitem',
|
||||
name='uid',
|
||||
field=models.CharField(db_index=True, max_length=44, null=True, validators=[django.core.validators.RegexValidator(message='Not a valid UID', regex='[a-zA-Z0-9]')]),
|
||||
),
|
||||
]
|
31
django_etesync/migrations/0029_auto_20200312_1849.py
Normal file
31
django_etesync/migrations/0029_auto_20200312_1849.py
Normal file
@ -0,0 +1,31 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-12 18:49
|
||||
|
||||
from django.db import migrations
|
||||
from django_etesync.serializers import generate_rev_uid
|
||||
|
||||
|
||||
def add_collection_main_item(apps, schema_editor):
|
||||
Collection = apps.get_model('django_etesync', 'Collection')
|
||||
CollectionItem = apps.get_model('django_etesync', 'CollectionItem')
|
||||
CollectionItemRevision = apps.get_model('django_etesync', 'CollectionItemRevision')
|
||||
|
||||
for col in Collection.objects.all():
|
||||
main_item = CollectionItem.objects.create(uid=None, encryptionKey=None, version=col.version, collection=col)
|
||||
col.mainItem = main_item
|
||||
col.save()
|
||||
|
||||
CollectionItemRevision.objects.create(
|
||||
uid=generate_rev_uid(),
|
||||
hmac='hmac-hash',
|
||||
item=main_item)
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_etesync', '0028_auto_20200312_1819'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(add_collection_main_item),
|
||||
]
|
19
django_etesync/migrations/0030_auto_20200312_1859.py
Normal file
19
django_etesync/migrations/0030_auto_20200312_1859.py
Normal file
@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.0.3 on 2020-03-12 18:59
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('django_etesync', '0029_auto_20200312_1849'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='collection',
|
||||
name='mainItem',
|
||||
field=models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='of_collection', to='django_etesync.CollectionItem'),
|
||||
),
|
||||
]
|
@ -29,6 +29,7 @@ class Collection(models.Model):
|
||||
max_length=44, validators=[UidValidator])
|
||||
version = models.PositiveSmallIntegerField()
|
||||
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
|
||||
mainItem = models.OneToOneField('CollectionItem', related_name='of_collection', on_delete=models.PROTECT)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('uid', 'owner')
|
||||
@ -36,19 +37,23 @@ class Collection(models.Model):
|
||||
def __str__(self):
|
||||
return self.uid
|
||||
|
||||
@cached_property
|
||||
def content(self):
|
||||
return self.mainItem.content
|
||||
|
||||
|
||||
class CollectionItem(models.Model):
|
||||
uid = models.CharField(db_index=True, blank=False, null=False,
|
||||
uid = models.CharField(db_index=True, blank=False, null=True,
|
||||
max_length=44, validators=[UidValidator])
|
||||
collection = models.ForeignKey(Collection, related_name='items', on_delete=models.CASCADE)
|
||||
version = models.PositiveSmallIntegerField()
|
||||
encryptionKey = models.BinaryField(editable=True, blank=False, null=False)
|
||||
encryptionKey = models.BinaryField(editable=True, blank=False, null=True)
|
||||
|
||||
class Meta:
|
||||
unique_together = ('uid', 'collection')
|
||||
|
||||
def __str__(self):
|
||||
return self.uid
|
||||
return '{} {}'.format(self.uid, self.collection.uid)
|
||||
|
||||
@cached_property
|
||||
def content(self):
|
||||
|
@ -43,44 +43,13 @@ class CollectionEncryptionKeyField(BinaryBase64Field):
|
||||
return None
|
||||
|
||||
|
||||
class CollectionSerializer(serializers.ModelSerializer):
|
||||
encryptionKey = CollectionEncryptionKeyField()
|
||||
accessLevel = serializers.SerializerMethodField('get_access_level_from_context')
|
||||
ctag = serializers.SerializerMethodField('get_ctag')
|
||||
|
||||
class Meta:
|
||||
model = models.Collection
|
||||
fields = ('uid', 'version', 'accessLevel', 'encryptionKey', 'ctag')
|
||||
|
||||
def get_access_level_from_context(self, obj):
|
||||
class CollectionContentField(BinaryBase64Field):
|
||||
def get_attribute(self, instance):
|
||||
request = self.context.get('request', None)
|
||||
if request is not None:
|
||||
return obj.members.get(user=request.user).accessLevel
|
||||
return instance.members.get(user=request.user).encryptionKey
|
||||
return None
|
||||
|
||||
def get_ctag(self, obj):
|
||||
last_revision = models.CollectionItemRevision.objects.filter(item__collection=obj).last()
|
||||
if last_revision is None:
|
||||
# FIXME: what is the etag for None? Though if we use the revision for collection it should be shared anyway.
|
||||
return None
|
||||
|
||||
return last_revision.uid
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Function that's called when this serializer creates an item"""
|
||||
encryption_key = validated_data.pop('encryptionKey')
|
||||
instance = self.__class__.Meta.model(**validated_data)
|
||||
|
||||
with transaction.atomic():
|
||||
instance.save()
|
||||
models.CollectionMember(collection=instance,
|
||||
user=validated_data.get('owner'),
|
||||
accessLevel=models.CollectionMember.AccessLevels.ADMIN,
|
||||
encryptionKey=encryption_key,
|
||||
).save()
|
||||
|
||||
return instance
|
||||
|
||||
|
||||
class CollectionItemChunkSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
@ -177,3 +146,53 @@ class CollectionItemSerializer(serializers.ModelSerializer):
|
||||
|
||||
class CollectionItemInlineSerializer(CollectionItemSerializer):
|
||||
content = CollectionItemRevisionInlineSerializer(read_only=True, many=False)
|
||||
|
||||
|
||||
class CollectionSerializer(serializers.ModelSerializer):
|
||||
encryptionKey = CollectionEncryptionKeyField()
|
||||
accessLevel = serializers.SerializerMethodField('get_access_level_from_context')
|
||||
ctag = serializers.SerializerMethodField('get_ctag')
|
||||
content = CollectionItemRevisionSerializer(many=False)
|
||||
|
||||
class Meta:
|
||||
model = models.Collection
|
||||
fields = ('uid', 'version', 'accessLevel', 'encryptionKey', 'content', 'ctag')
|
||||
|
||||
def get_access_level_from_context(self, obj):
|
||||
request = self.context.get('request', None)
|
||||
if request is not None:
|
||||
return obj.members.get(user=request.user).accessLevel
|
||||
return None
|
||||
|
||||
def get_ctag(self, obj):
|
||||
last_revision = models.CollectionItemRevision.objects.filter(item__collection=obj).last()
|
||||
if last_revision is None:
|
||||
# FIXME: what is the etag for None? Though if we use the revision for collection it should be shared anyway.
|
||||
return None
|
||||
|
||||
return last_revision.uid
|
||||
|
||||
def create(self, validated_data):
|
||||
"""Function that's called when this serializer creates an item"""
|
||||
revision_data = validated_data.pop('content')
|
||||
encryption_key = validated_data.pop('encryptionKey')
|
||||
instance = self.__class__.Meta.model(**validated_data)
|
||||
|
||||
with transaction.atomic():
|
||||
main_item = models.CollectionItem.objects.create(
|
||||
uid=None, encryptionKey=None, version=instance.version, collection=instance)
|
||||
instance.mainItem = main_item
|
||||
|
||||
chunks = revision_data.pop('chunks')
|
||||
revision = models.CollectionItemRevision.objects.create(**revision_data, uid=generate_rev_uid(),
|
||||
item=main_item)
|
||||
revision.chunks.set(chunks)
|
||||
|
||||
instance.save()
|
||||
models.CollectionMember(collection=instance,
|
||||
user=validated_data.get('owner'),
|
||||
accessLevel=models.CollectionMember.AccessLevels.ADMIN,
|
||||
encryptionKey=encryption_key,
|
||||
).save()
|
||||
|
||||
return instance
|
||||
|
Loading…
Reference in New Issue
Block a user