|
|
import xml.etree.ElementTree as et
|
|
|
|
|
|
from django.db import models
|
|
|
|
|
|
from boards.models import KeyPair
|
|
|
|
|
|
TAG_MODEL = 'model'
|
|
|
TAG_REQUEST = 'request'
|
|
|
TAG_ID = 'id'
|
|
|
|
|
|
TYPE_GET = 'get'
|
|
|
TYPE_LIST = 'list'
|
|
|
|
|
|
ATTR_VERSION = 'version'
|
|
|
ATTR_TYPE = 'type'
|
|
|
ATTR_NAME = 'name'
|
|
|
|
|
|
ATTR_KEY = 'key'
|
|
|
ATTR_KEY_TYPE = 'type'
|
|
|
ATTR_LOCAL_ID = 'local-id'
|
|
|
|
|
|
|
|
|
class GlobalIdManager(models.Manager):
|
|
|
def global_id_exists(self, global_id):
|
|
|
"""
|
|
|
Checks if the same global id already exists in the system.
|
|
|
"""
|
|
|
|
|
|
return self.filter(key=global_id.key,
|
|
|
key_type=global_id.key_type,
|
|
|
local_id=global_id.local_id).exists()
|
|
|
|
|
|
|
|
|
class GlobalId(models.Model):
|
|
|
"""
|
|
|
Global model ID and cache.
|
|
|
Key, key type and local ID make a single global identificator of the model.
|
|
|
Content is an XML cache of the model that can be passed along between nodes
|
|
|
without manual serialization each time.
|
|
|
"""
|
|
|
class Meta:
|
|
|
app_label = 'boards'
|
|
|
|
|
|
objects = GlobalIdManager()
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
models.Model.__init__(self, *args, **kwargs)
|
|
|
|
|
|
if 'key' in kwargs and 'key_type' in kwargs and 'local_id' in kwargs:
|
|
|
self.key = kwargs['key']
|
|
|
self.key_type = kwargs['key_type']
|
|
|
self.local_id = kwargs['local_id']
|
|
|
|
|
|
key = models.TextField()
|
|
|
key_type = models.TextField()
|
|
|
local_id = models.IntegerField()
|
|
|
content = models.TextField(blank=True, null=True)
|
|
|
|
|
|
def __str__(self):
|
|
|
return '%s::%s::%d' % (self.key_type, self.key, self.local_id)
|
|
|
|
|
|
def to_xml_element(self, element: et.Element):
|
|
|
"""
|
|
|
Exports global id to an XML element.
|
|
|
"""
|
|
|
|
|
|
element.set(ATTR_KEY, self.key)
|
|
|
element.set(ATTR_KEY_TYPE, self.key_type)
|
|
|
element.set(ATTR_LOCAL_ID, str(self.local_id))
|
|
|
|
|
|
@staticmethod
|
|
|
def from_xml_element(element: et.Element):
|
|
|
"""
|
|
|
Parses XML id tag and gets global id from it.
|
|
|
|
|
|
Arguments:
|
|
|
element -- the XML 'id' element
|
|
|
|
|
|
Returns:
|
|
|
global_id -- id itself
|
|
|
exists -- True if the global id was taken from database, False if it
|
|
|
did not exist and was created.
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
return GlobalId.objects.get(key=element.get(ATTR_KEY),
|
|
|
key_type=element.get(ATTR_KEY_TYPE),
|
|
|
local_id=int(element.get(
|
|
|
ATTR_LOCAL_ID))), True
|
|
|
except GlobalId.DoesNotExist:
|
|
|
return GlobalId(key=element.get(ATTR_KEY),
|
|
|
key_type=element.get(ATTR_KEY_TYPE),
|
|
|
local_id=int(element.get(ATTR_LOCAL_ID))), False
|
|
|
|
|
|
def is_local(self):
|
|
|
"""Checks fo the ID is local model's"""
|
|
|
return KeyPair.objects.filter(
|
|
|
key_type=self.key_type, public_key=self.key).exists()
|
|
|
|
|
|
def clear_cache(self):
|
|
|
"""
|
|
|
Removes content cache and signatures.
|
|
|
"""
|
|
|
self.content = None
|
|
|
self.save()
|
|
|
self.signature_set.all().delete()
|
|
|
|
|
|
|
|
|
class Signature(models.Model):
|
|
|
class Meta:
|
|
|
app_label = 'boards'
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
models.Model.__init__(self, *args, **kwargs)
|
|
|
|
|
|
if 'key' in kwargs and 'key_type' in kwargs and 'signature' in kwargs:
|
|
|
self.key_type = kwargs['key_type']
|
|
|
self.key = kwargs['key']
|
|
|
self.signature = kwargs['signature']
|
|
|
|
|
|
key_type = models.TextField()
|
|
|
key = models.TextField()
|
|
|
signature = models.TextField()
|
|
|
|
|
|
global_id = models.ForeignKey('GlobalId', on_delete=models.CASCADE)
|
|
|
|