110 lines
4.3 KiB
Python
110 lines
4.3 KiB
Python
import logging
|
|
|
|
from django.db import models
|
|
from django.utils.translation import ugettext_lazy as _
|
|
|
|
from documents.models import DocumentVersion, get_filename_from_uuid
|
|
from documents.conf.settings import STORAGE_BACKEND
|
|
from django_gpg.runtime import gpg
|
|
from django_gpg.exceptions import GPGVerificationError, GPGDecryptionError
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class DocumentVersionSignatureManager(models.Manager):
|
|
#def update_signed_state(self, document):
|
|
# document_signature, created = self.model.get_or_create(
|
|
# document_version=document.latest_version,
|
|
# )
|
|
# if document.exists():
|
|
# descriptor = document.open()
|
|
# try:
|
|
# document_signature.signature_state = gpg.verify_file(descriptor).status
|
|
# # TODO: give use choice for auto public key fetch?
|
|
# # OR maybe new config option
|
|
# except GPGVerificationError:
|
|
# document_signature.signature_state = None
|
|
# finally:
|
|
# document_signature.save()
|
|
|
|
def add_detached_signature(self, document, detached_signature):
|
|
document_signature, created = self.model.objects.get_or_create(
|
|
document_version=document.latest_version,
|
|
)
|
|
if not self.signature_state(document):
|
|
document_signature.signature_file = detached_signature
|
|
document_signature.save()
|
|
else:
|
|
raise Exception('document already has an embedded signature')
|
|
|
|
def has_detached_signature(self, document):
|
|
document_signature, created = self.model.objects.get_or_create(
|
|
document_version=document.latest_version,
|
|
)
|
|
if document_signature.signature_file:
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def has_embedded_signature(self, document):
|
|
logger.debug('document: %s' % document)
|
|
|
|
if self.signature_state(document):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def signature_state(self, document):
|
|
document_signature, created = self.model.objects.get_or_create(
|
|
document_version=document.latest_version,
|
|
)
|
|
logger.debug('created: %s' % created)
|
|
if created and document.exists():
|
|
descriptor = document.open(raw=True)
|
|
try:
|
|
document_signature.signature_state = gpg.verify_file(descriptor).status
|
|
# TODO: give use choice for auto public key fetch?
|
|
# OR maybe new config option
|
|
except GPGVerificationError:
|
|
document_signature.signature_state = None
|
|
finally:
|
|
document_signature.save()
|
|
|
|
#document_signature.signature_state = self.verify_signature(document).status
|
|
#document_signature.save()
|
|
|
|
return document_signature.signature_state
|
|
|
|
def detached_signature(self, document):
|
|
document_signature, created = self.model.objects.get_or_create(
|
|
document_version=document.latest_version,
|
|
)
|
|
return document_signature.signature_file.storage.open(document_signature.signature_file.path)
|
|
|
|
def verify_signature(self, document):
|
|
if self.has_detached_signature(document):
|
|
logger.debug('has detached signature')
|
|
args = (document.open(), self.detached_signature(document))
|
|
else:
|
|
args = (document.open(raw=True),)
|
|
|
|
try:
|
|
return gpg.verify_w_retry(*args)
|
|
except GPGVerificationError:
|
|
return None
|
|
|
|
|
|
class DocumentVersionSignature(models.Model):
|
|
'''
|
|
Model that describes a document version signature properties
|
|
'''
|
|
document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'), editable=False)
|
|
signature_state = models.CharField(blank=True, null=True, max_length=16, verbose_name=_(u'signature state'), editable=False)
|
|
signature_file = models.FileField(blank=True, null=True, upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'signature file'), editable=False)
|
|
|
|
objects = DocumentVersionSignatureManager()
|
|
|
|
class Meta:
|
|
verbose_name = _(u'document version signature')
|
|
verbose_name_plural = _(u'document version signatures')
|