Update and re enable document_signature app

This commit is contained in:
Roberto Rosario
2012-09-16 03:57:46 -04:00
parent 0d382a7dd8
commit b85431a4dc
14 changed files with 137 additions and 104 deletions

View File

@@ -1,85 +1 @@
from __future__ import absolute_import
import logging
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
#from django.db.models.signals import post_save
#from django.dispatch import receiver
from documents.models import Document, DocumentVersion
from navigation.api import bind_links
from django_gpg.runtime import gpg
from django_gpg.exceptions import GPGDecryptionError
from acls.api import class_permissions
from .models import DocumentVersionSignature
from .permissions import (
PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE
)
from .links import (document_signature_upload, document_signature_download,
document_signature_delete, document_verify)
logger = logging.getLogger(__name__)
def document_pre_open_hook(descriptor, instance):
if DocumentVersionSignature.objects.has_embedded_signature(instance.document):
# If it has an embedded signature decrypt
try:
result = gpg.decrypt_file(descriptor, close_descriptor=False)
# gpg return a string, turn it into a file like object
except GPGDecryptionError:
# At least return the original raw content
descriptor.seek(0)
return descriptor
else:
descriptor.close()
return StringIO(result.data)
else:
# It no embedded signature pass along
# Doing this single DB lookup avoids trying to decrypt non signed
# files always, which could result in slow down for big non signed
# files
#descriptor.seek(0)
return descriptor
#try:
# result = gpg.decrypt_file(descriptor, close_descriptor=False)
# # gpg return a string, turn it into a file like object
#except GPGDecryptionError:
# # At least return the original raw content
# descriptor.seek(0)
# return descriptor
#else:
# descriptor.close()
# return StringIO(result.data)
def document_post_save_hook(instance):
if not instance.pk:
document_signature, created = DocumentVersionSignature.objects.get_or_create(
document_version=instance.latest_version,
)
#DocumentVersionSignature.objects.update_signed_state(instance.document)
#@receiver(post_save, dispatch_uid='check_document_signature_state', sender=DocumentVersion)
#def check_document_signature_state(sender, instance, **kwargs):
# if kwargs.get('created', False):
# DocumentVersionSignature.objects.signature_state(instance.document)
bind_links([Document], [document_verify], menu_name='form_header')
bind_links(['document_verify', 'document_signature_upload', 'document_signature_download', 'document_signature_delete'], [document_signature_upload, document_signature_download, document_signature_delete], menu_name='sidebar')
DocumentVersion.register_pre_open_hook(1, document_pre_open_hook)
DocumentVersion.register_post_save_hook(1, document_post_save_hook)
class_permissions(Document, [
PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE
])

View File

@@ -1,9 +1,5 @@
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
#from django.utils.translation import ugettext
#from django.core.urlresolvers import reverse
#from django.utils.safestring import mark_safe
#from django.conf import settings
class DetachedSignatureForm(forms.Form): class DetachedSignatureForm(forms.Form):

View File

@@ -0,0 +1,9 @@
from __future__ import absolute_import
from icons.literals import PENCIL_ADD, DISK, PENCIL_DELETE, TEXT_SIGNATURE
from icons import Icon
icon_document_signature_upload = Icon(PENCIL_ADD)
icon_document_signature_download = Icon(DISK)
icon_document_signature_delete = Icon(PENCIL_DELETE)
icon_document_verify = Icon(TEXT_SIGNATURE)

View File

@@ -9,6 +9,8 @@ from .permissions import (
PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD, PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE
) )
from .icons import (icon_document_signature_upload, icon_document_signature_download,
icon_document_signature_delete, icon_document_verify)
def has_embedded_signature(context): def has_embedded_signature(context):
@@ -18,7 +20,8 @@ def has_embedded_signature(context):
def doesnt_have_detached_signature(context): def doesnt_have_detached_signature(context):
return DocumentVersionSignature.objects.has_detached_signature(context['object']) == False return DocumentVersionSignature.objects.has_detached_signature(context['object']) == False
document_signature_upload = Link(text=_(u'upload signature'), view='document_signature_upload', args='object.pk', sprite='pencil_add', permissions=[PERMISSION_SIGNATURE_UPLOAD], conditional_disable=has_embedded_signature)
document_signature_download = Link(text=_(u'download signature'), view='document_signature_download', args='object.pk', sprite='disk', permissions=[PERMISSION_SIGNATURE_DOWNLOAD], conditional_disable=doesnt_have_detached_signature) document_signature_upload = Link(text=_(u'upload signature'), view='document_signature_upload', args='object.pk', icon=icon_document_signature_upload, permissions=[PERMISSION_SIGNATURE_UPLOAD], conditional_disable=has_embedded_signature)
document_signature_delete = Link(text=_(u'delete signature'), view='document_signature_delete', args='object.pk', sprite='pencil_delete', permissions=[PERMISSION_SIGNATURE_DELETE], conditional_disable=doesnt_have_detached_signature) document_signature_download = Link(text=_(u'download signature'), view='document_signature_download', args='object.pk', icon=icon_document_signature_download, permissions=[PERMISSION_SIGNATURE_DOWNLOAD], conditional_disable=doesnt_have_detached_signature)
document_verify = Link(text=_(u'signatures'), view='document_verify', args='object.pk', sprite='text_signature', permissions=[PERMISSION_DOCUMENT_VERIFY]) document_signature_delete = Link(text=_(u'delete signature'), view='document_signature_delete', args='object.pk', icon=icon_document_signature_delete, permissions=[PERMISSION_SIGNATURE_DELETE], conditional_disable=doesnt_have_detached_signature)
document_verify = Link(text=_(u'signatures'), view='document_verify', args='object.pk', icon=icon_document_verify, permissions=[PERMISSION_DOCUMENT_VERIFY])

View File

@@ -2,7 +2,6 @@ import logging
from django.db import models from django.db import models
from django_gpg.runtime import gpg
from django_gpg.exceptions import GPGVerificationError from django_gpg.exceptions import GPGVerificationError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -52,6 +51,8 @@ class DocumentVersionSignatureManager(models.Manager):
return document_signature.signature_file.storage.open(document_signature.signature_file.path) return document_signature.signature_file.storage.open(document_signature.signature_file.path)
def verify_signature(self, document): def verify_signature(self, document):
from django_gpg.runtime import gpg
document_descriptor = document.open(raw=True) document_descriptor = document.open(raw=True)
detached_signature = None detached_signature = None
if self.has_detached_signature(document): if self.has_detached_signature(document):

View File

@@ -5,8 +5,6 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from documents.models import DocumentVersion, get_filename_from_uuid from documents.models import DocumentVersion, get_filename_from_uuid
from documents.conf.settings import STORAGE_BACKEND
from django_gpg.runtime import gpg
from .managers import DocumentVersionSignatureManager from .managers import DocumentVersionSignatureManager
@@ -18,7 +16,7 @@ class DocumentVersionSignature(models.Model):
Model that describes a document version signature properties Model that describes a document version signature properties
""" """
document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'), editable=False) document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'), 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) signature_file = models.FileField(blank=True, null=True, upload_to=get_filename_from_uuid, verbose_name=_(u'signature file'), editable=False)
has_embedded_signature = models.BooleanField(default=False, verbose_name=_(u'has embedded signature'), editable=False) has_embedded_signature = models.BooleanField(default=False, verbose_name=_(u'has embedded signature'), editable=False)
objects = DocumentVersionSignatureManager() objects = DocumentVersionSignatureManager()
@@ -27,6 +25,8 @@ class DocumentVersionSignature(models.Model):
self.signature_file.storage.delete(self.signature_file.path) self.signature_file.storage.delete(self.signature_file.path)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
from django_gpg.runtime import gpg
if not self.pk: if not self.pk:
descriptor = self.document_version.open(raw=True) descriptor = self.document_version.open(raw=True)
self.has_embedded_signature = gpg.has_embedded_signature(descriptor) self.has_embedded_signature = gpg.has_embedded_signature(descriptor)

View File

@@ -0,0 +1,89 @@
from __future__ import absolute_import
import logging
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
#from django.db.models.signals import post_save
#from django.dispatch import receiver
from documents.models import Document, DocumentVersion
from navigation.api import bind_links
from django_gpg.runtime import gpg
from django_gpg.exceptions import GPGDecryptionError
from acls.api import class_permissions
from documents.settings import STORAGE_BACKEND
from .models import DocumentVersionSignature
from .permissions import (
PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE
)
from .links import (document_signature_upload, document_signature_download,
document_signature_delete, document_verify)
logger = logging.getLogger(__name__)
def document_pre_open_hook(descriptor, instance):
if DocumentVersionSignature.objects.has_embedded_signature(instance.document):
# If it has an embedded signature decrypt
try:
result = gpg.decrypt_file(descriptor, close_descriptor=False)
# gpg return a string, turn it into a file like object
except GPGDecryptionError:
# At least return the original raw content
descriptor.seek(0)
return descriptor
else:
descriptor.close()
return StringIO(result.data)
else:
# It no embedded signature pass along
# Doing this single DB lookup avoids trying to decrypt non signed
# files always, which could result in slow down for big non signed
# files
#descriptor.seek(0)
return descriptor
#try:
# result = gpg.decrypt_file(descriptor, close_descriptor=False)
# # gpg return a string, turn it into a file like object
#except GPGDecryptionError:
# # At least return the original raw content
# descriptor.seek(0)
# return descriptor
#else:
# descriptor.close()
# return StringIO(result.data)
def document_post_save_hook(instance):
if not instance.pk:
document_signature, created = DocumentVersionSignature.objects.get_or_create(
document_version=instance.latest_version,
)
#DocumentVersionSignature.objects.update_signed_state(instance.document)
#@receiver(post_save, dispatch_uid='check_document_signature_state', sender=DocumentVersion)
#def check_document_signature_state(sender, instance, **kwargs):
# if kwargs.get('created', False):
# DocumentVersionSignature.objects.signature_state(instance.document)
def init_app():
bind_links([Document], [document_verify], menu_name='form_header')
bind_links(['document_verify', 'document_signature_upload', 'document_signature_download', 'document_signature_delete'], [document_signature_upload, document_signature_download, document_signature_delete], menu_name='sidebar')
DocumentVersion.register_pre_open_hook(1, document_pre_open_hook)
DocumentVersion.register_post_save_hook(1, document_post_save_hook)
class_permissions(Document, [
PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE
])
DocumentVersionSignature._meta.get_field('signature_file').storage=STORAGE_BACKEND()

View File

@@ -0,0 +1,10 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from .icons import icon_document_verify
label = _(u'Document signatures')
description = _(u'Handles document signatures.')
dependencies = ['app_registry', 'icons', 'navigation', 'django_gpg', 'documents', 'permissions']
icon = icon_document_verify

View File

@@ -20,7 +20,7 @@ from acls.models import AccessEntry
from django_gpg.api import SIGNATURE_STATES from django_gpg.api import SIGNATURE_STATES
from . import (PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD, from .permissions import (PERMISSION_DOCUMENT_VERIFY, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE) PERMISSION_SIGNATURE_DOWNLOAD, PERMISSION_SIGNATURE_DELETE)
from .forms import DetachedSignatureForm from .forms import DetachedSignatureForm
from .models import DocumentVersionSignature from .models import DocumentVersionSignature
@@ -42,10 +42,9 @@ def document_verify(request, document_pk):
signature_state = SIGNATURE_STATES.get(getattr(signature, 'status', None)) signature_state = SIGNATURE_STATES.get(getattr(signature, 'status', None))
widget = (u'<img style="vertical-align: middle;" src="%simages/icons/%s" />' % (settings.STATIC_URL, signature_state['icon']))
paragraphs = [ paragraphs = [
_(u'Signature status: %(widget)s %(text)s') % { _(u'Signature status: %(icon)s %(text)s') % {
'widget': mark_safe(widget), 'icon': signature_state['icon'].display_big(),
'text': signature_state['text'] 'text': signature_state['text']
}, },
] ]

View File

@@ -21,7 +21,7 @@ class Icon(object):
return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_url(self, size) return IconSetBase.get_by_name(self.icon_set or ICON_SET).get_url(self, size)
def display(self, size): # TODO: move to widgets? def display(self, size): # TODO: move to widgets?
return mark_safe('<img src="%sicons/%s" />' % (settings.STATIC_URL, self.get_url(size))) return mark_safe('<img style="vertical-align: middle;" src="%sicons/%s" />' % (settings.STATIC_URL, self.get_url(size)))
def display_small(self): def display_small(self):
return self.display(SIZE_SMALL) return self.display(SIZE_SMALL)

View File

@@ -39,6 +39,7 @@ class IconSet(IconSetBase):
DATABASE_EDIT: 'database_edit.png', DATABASE_EDIT: 'database_edit.png',
DATABASE_DELETE: 'database_delete.png', DATABASE_DELETE: 'database_delete.png',
DELETE: 'delete.png', DELETE: 'delete.png',
DISK: 'disk.png',
DRAW_AIRBRUSH: 'draw_airbrush.png', DRAW_AIRBRUSH: 'draw_airbrush.png',
DOCUMENT_SIGNATURE: 'document_signature.png', DOCUMENT_SIGNATURE: 'document_signature.png',
ERROR: 'error.png', ERROR: 'error.png',
@@ -99,6 +100,8 @@ class IconSet(IconSetBase):
PAGE_WHITE_PICTURE: 'page_white_picture.png', PAGE_WHITE_PICTURE: 'page_white_picture.png',
PAGE_WHITE_TEXT: 'page_white_text.png', PAGE_WHITE_TEXT: 'page_white_text.png',
PAGE_WORLD: 'page_world.png', PAGE_WORLD: 'page_world.png',
PENCIL_ADD: 'pencil_add.png',
PENCIL_DELETE: 'pencil_delete.png',
PICTURES: 'pictures.png', PICTURES: 'pictures.png',
PILL: 'pill.png', PILL: 'pill.png',
PLUGIN: 'plugin.png', PLUGIN: 'plugin.png',
@@ -123,6 +126,7 @@ class IconSet(IconSetBase):
TAG_BLUE_DELETE: 'tag_blue_delete.png', TAG_BLUE_DELETE: 'tag_blue_delete.png',
TAG_BLUE_EDIT: 'tag_blue_edit.png', TAG_BLUE_EDIT: 'tag_blue_edit.png',
TEXT_DROPCAPS: 'text_dropcaps.png', TEXT_DROPCAPS: 'text_dropcaps.png',
TEXT_SIGNATURE: 'text_signature.png',
TEXT_STRIKETHROUGH: 'text_strikethrough.png', TEXT_STRIKETHROUGH: 'text_strikethrough.png',
THEATER: 'theater.png', THEATER: 'theater.png',
TICK: 'tick.png', TICK: 'tick.png',
@@ -131,7 +135,8 @@ class IconSet(IconSetBase):
USER: 'user.png', USER: 'user.png',
USER_ADD:'user_add.png', USER_ADD:'user_add.png',
USER_EDIT: 'user_edit.png', USER_EDIT: 'user_edit.png',
USER_DELETE: 'user_delete.png', USER_DELETE: 'user_delete.png',
USER_SILHOUETTE: 'user_silhouette.png',
VCARD: 'vcard.png', VCARD: 'vcard.png',
VCARD_EDIT: 'vcard_edit.png', VCARD_EDIT: 'vcard_edit.png',
WRENCH: 'wrench.png', WRENCH: 'wrench.png',

View File

@@ -33,6 +33,7 @@ DATABASE_ADD = 'database_add'
DATABASE_EDIT = 'database_edit' DATABASE_EDIT = 'database_edit'
DATABASE_DELETE = 'database_delete' DATABASE_DELETE = 'database_delete'
DELETE = 'delete' DELETE = 'delete'
DISK = 'disk'
DRAW_AIRBRUSH = 'draw_airbrush' DRAW_AIRBRUSH = 'draw_airbrush'
DOCUMENT_SIGNATURE = 'document_signature' DOCUMENT_SIGNATURE = 'document_signature'
ERROR = 'error' ERROR = 'error'
@@ -95,6 +96,8 @@ PAGE_WHITE_EDIT = 'page_white_edit'
PAGE_WHITE_PICTURE = 'page_white_picture' PAGE_WHITE_PICTURE = 'page_white_picture'
PAGE_WHITE_TEXT = 'page_white_text' PAGE_WHITE_TEXT = 'page_white_text'
PAGE_WORLD = 'page_world' PAGE_WORLD = 'page_world'
PENCIL_ADD = 'pencil_add'
PENCIL_DELETE = 'pencil_delete'
PICTURES = 'pictures' PICTURES = 'pictures'
PILL = 'pill' PILL = 'pill'
PLUGIN = 'plugin' PLUGIN = 'plugin'
@@ -119,6 +122,7 @@ TAG_BLUE_ADD = 'tag_blue_add'
TAG_BLUE_DELETE = 'tag_blue_delete' TAG_BLUE_DELETE = 'tag_blue_delete'
TAG_BLUE_EDIT = 'tag_blue_edit' TAG_BLUE_EDIT = 'tag_blue_edit'
TEXT_DROPCAPS = 'text_dropcaps' TEXT_DROPCAPS = 'text_dropcaps'
TEXT_SIGNATURE = 'text_signature'
TEXT_STRIKETHROUGH = 'text_strikethrough' TEXT_STRIKETHROUGH = 'text_strikethrough'
THEATER = 'theater' THEATER = 'theater'
TICK = 'tick' TICK = 'tick'
@@ -128,6 +132,7 @@ USER = 'user'
USER_ADD = 'user_add' USER_ADD = 'user_add'
USER_EDIT = 'user_edit' USER_EDIT = 'user_edit'
USER_DELETE = 'user_delete' USER_DELETE = 'user_delete'
USER_SILHOUETTE = 'user_silhouette'
VCARD = 'vcard' VCARD = 'vcard'
VCARD_EDIT = 'vcard_edit' VCARD_EDIT = 'vcard_edit'
WRENCH = 'wrench' WRENCH = 'wrench'

View File

@@ -175,7 +175,7 @@ INSTALLED_APPS = (
'folders', 'folders',
'dynamic_search', 'dynamic_search',
'document_comments', 'document_comments',
#'document_signatures', 'document_signatures',
'linking', 'linking',
'metadata', 'metadata',
'ocr', 'ocr',

View File

@@ -29,7 +29,7 @@ urlpatterns = patterns('',
#(r'^document_acls/', include('document_acls.urls')), #(r'^document_acls/', include('document_acls.urls')),
(r'^api/', include('rest_api.urls')), (r'^api/', include('rest_api.urls')),
(r'^gpg/', include('django_gpg.urls')), (r'^gpg/', include('django_gpg.urls')),
#(r'^documents/signatures/', include('document_signatures.urls')), (r'^documents/signatures/', include('document_signatures.urls')),
#(r'^mailer/', include('mailer.urls')), #(r'^mailer/', include('mailer.urls')),
#(r'^workflows/', include('workflows.urls')), #(r'^workflows/', include('workflows.urls')),
#(r'^checkouts/', include('checkouts.urls')), #(r'^checkouts/', include('checkouts.urls')),