Merge branch 'release/v0.12'

Conflicts:
	apps/documents/models.py
	apps/history/api.py
	apps/ocr/__init__.py
This commit is contained in:
Roberto Rosario
2012-02-27 12:57:11 -04:00
635 changed files with 37372 additions and 11328 deletions

View File

@@ -1,36 +1,41 @@
from __future__ import absolute_import
import tempfile
from django.utils.translation import ugettext_lazy as _
from common.utils import validate_path, encapsulate
from navigation.api import register_links, register_top_menu, \
register_model_list_columns, register_multi_item_links, \
register_sidebar_template
from navigation.api import (register_links, register_top_menu,
register_model_list_columns, register_multi_item_links,
register_sidebar_template)
from main.api import register_diagnostic, register_maintenance_links
from permissions.api import register_permission, set_namespace_title
from tags.widgets import get_tags_inline_widget_simple
from history.api import register_history_type
from history.permissions import PERMISSION_HISTORY_VIEW
from metadata.api import get_metadata_string
from project_setup.api import register_setup
from acls.api import class_permissions
from documents.models import (Document, DocumentPage,
from .models import (Document, DocumentPage,
DocumentPageTransformation, DocumentType, DocumentTypeFilename,
DocumentVersion)
from documents.literals import (PERMISSION_DOCUMENT_CREATE,
from .permissions import (PERMISSION_DOCUMENT_CREATE,
PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_VIEW,
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD,
PERMISSION_DOCUMENT_TRANSFORM, PERMISSION_DOCUMENT_TOOLS,
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_VERSION_REVERT)
from documents.literals import (PERMISSION_DOCUMENT_TYPE_EDIT,
PERMISSION_DOCUMENT_TYPE_DELETE, PERMISSION_DOCUMENT_TYPE_CREATE)
from documents.literals import (HISTORY_DOCUMENT_CREATED,
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_VERSION_REVERT,
PERMISSION_DOCUMENT_TYPE_EDIT, PERMISSION_DOCUMENT_TYPE_DELETE,
PERMISSION_DOCUMENT_TYPE_CREATE, PERMISSION_DOCUMENT_TYPE_VIEW,
PERMISSION_DOCUMENT_NEW_VERSION)
from .literals import (HISTORY_DOCUMENT_CREATED,
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED)
from documents.conf.settings import ZOOM_MAX_LEVEL
from documents.conf.settings import ZOOM_MIN_LEVEL
from documents.conf import settings as document_settings
from documents.widgets import document_thumbnail
from .conf.settings import ZOOM_MAX_LEVEL
from .conf.settings import ZOOM_MIN_LEVEL
from .conf import settings as document_settings
from .widgets import document_thumbnail
# Document page links expressions
def is_first_page(context):
return context['page'].page_number <= 1
@@ -50,31 +55,13 @@ def is_max_zoom(context):
def is_current_version(context):
return context['object'].document.latest_version.timestamp == context['object'].timestamp
# Permission setup
set_namespace_title('documents', _(u'Documents'))
register_permission(PERMISSION_DOCUMENT_CREATE)
register_permission(PERMISSION_DOCUMENT_PROPERTIES_EDIT)
register_permission(PERMISSION_DOCUMENT_EDIT)
register_permission(PERMISSION_DOCUMENT_VIEW)
register_permission(PERMISSION_DOCUMENT_DELETE)
register_permission(PERMISSION_DOCUMENT_DOWNLOAD)
register_permission(PERMISSION_DOCUMENT_TRANSFORM)
register_permission(PERMISSION_DOCUMENT_TOOLS)
register_permission(PERMISSION_DOCUMENT_VERSION_REVERT)
# Document type permissions
set_namespace_title('documents_setup', _(u'Documents setup'))
register_permission(PERMISSION_DOCUMENT_TYPE_EDIT)
register_permission(PERMISSION_DOCUMENT_TYPE_DELETE)
register_permission(PERMISSION_DOCUMENT_TYPE_CREATE)
# History setup
register_history_type(HISTORY_DOCUMENT_CREATED)
register_history_type(HISTORY_DOCUMENT_EDITED)
register_history_type(HISTORY_DOCUMENT_DELETED)
document_list = {'text': _(u'all documents'), 'view': 'document_list', 'famfam': 'page', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_list_recent = {'text': _(u'recent documents'), 'view': 'document_list_recent', 'famfam': 'page', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_list = {'text': _(u'all documents'), 'view': 'document_list', 'famfam': 'page'}
document_list_recent = {'text': _(u'recent documents'), 'view': 'document_list_recent', 'famfam': 'page'}
document_create_multiple = {'text': _(u'upload new documents'), 'view': 'document_create_multiple', 'famfam': 'page_add', 'permissions': [PERMISSION_DOCUMENT_CREATE], 'children_view_regex': [r'upload_interactive']}
document_create_siblings = {'text': _(u'clone metadata'), 'view': 'document_create_siblings', 'args': 'object.id', 'famfam': 'page_copy', 'permissions': [PERMISSION_DOCUMENT_CREATE]}
document_view_simple = {'text': _(u'details'), 'view': 'document_view_simple', 'args': 'object.id', 'famfam': 'page', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
@@ -84,6 +71,7 @@ document_multiple_delete = {'text': _(u'delete'), 'view': 'document_multiple_del
document_edit = {'text': _(u'edit'), 'view': 'document_edit', 'args': 'object.id', 'famfam': 'page_edit', 'permissions': [PERMISSION_DOCUMENT_PROPERTIES_EDIT]}
document_preview = {'text': _(u'preview'), 'class': 'fancybox', 'view': 'document_preview', 'args': 'object.id', 'famfam': 'magnifier', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_download = {'text': _(u'download'), 'view': 'document_download', 'args': 'object.id', 'famfam': 'page_save', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}
document_multiple_download = {'text': _(u'download'), 'view': 'document_multiple_download', 'famfam': 'page_save', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}
document_version_download = {'text': _(u'download'), 'view': 'document_version_download', 'args': 'object.pk', 'famfam': 'page_save', 'permissions': [PERMISSION_DOCUMENT_DOWNLOAD]}
document_find_duplicates = {'text': _(u'find duplicates'), 'view': 'document_find_duplicates', 'args': 'object.id', 'famfam': 'page_white_copy', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_find_all_duplicates = {'text': _(u'find all duplicates'), 'view': 'document_find_all_duplicates', 'famfam': 'page_white_copy', 'permissions': [PERMISSION_DOCUMENT_VIEW], 'description': _(u'Search all the documents\' checksums and return a list of the exact matches.')}
@@ -91,7 +79,7 @@ document_update_page_count = {'text': _(u'update office documents\' page count')
document_clear_transformations = {'text': _(u'clear transformations'), 'view': 'document_clear_transformations', 'args': 'object.id', 'famfam': 'page_paintbrush', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}
document_multiple_clear_transformations = {'text': _(u'clear transformations'), 'view': 'document_multiple_clear_transformations', 'famfam': 'page_paintbrush', 'permissions': [PERMISSION_DOCUMENT_TRANSFORM]}
document_print = {'text': _(u'print'), 'view': 'document_print', 'args': 'object.id', 'famfam': 'printer', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_history_view = {'text': _(u'history'), 'view': 'history_for_object', 'args': ['"documents"', '"document"', 'object.id'], 'famfam': 'book_go', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_history_view = {'text': _(u'history'), 'view': 'history_for_object', 'args': ['"documents"', '"document"', 'object.id'], 'famfam': 'book_go', 'permissions': [PERMISSION_HISTORY_VIEW]}
document_missing_list = {'text': _(u'Find missing document files'), 'view': 'document_missing_list', 'famfam': 'folder_page', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
# Tools
@@ -121,14 +109,14 @@ document_version_list = {'text': _(u'versions'), 'view': 'document_version_list'
document_version_revert = {'text': _(u'revert'), 'view': 'document_version_revert', 'args': 'object.pk', 'famfam': 'page_refresh', 'permissions': [PERMISSION_DOCUMENT_VERSION_REVERT], 'conditional_disable': is_current_version}
# Document type related links
document_type_list = {'text': _(u'document type list'), 'view': 'document_type_list', 'famfam': 'layout', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_type_setup = {'text': _(u'document types'), 'view': 'document_type_list', 'famfam': 'layout', 'icon': 'layout.png', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_type_document_list = {'text': _(u'documents of this type'), 'view': 'document_type_document_list', 'args': 'document_type.id', 'famfam': 'page_go', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_type_list = {'text': _(u'document type list'), 'view': 'document_type_list', 'famfam': 'layout', 'permissions': [PERMISSION_DOCUMENT_TYPE_VIEW]}
document_type_setup = {'text': _(u'document types'), 'view': 'document_type_list', 'famfam': 'layout', 'icon': 'layout.png', 'permissions': [PERMISSION_DOCUMENT_TYPE_VIEW], 'children_view_regex': [r'^document_type_']}
document_type_document_list = {'text': _(u'documents of this type'), 'view': 'document_type_document_list', 'args': 'document_type.id', 'famfam': 'page_go', 'permissions': [PERMISSION_DOCUMENT_TYPE_VIEW]}
document_type_edit = {'text': _(u'edit'), 'view': 'document_type_edit', 'args': 'document_type.id', 'famfam': 'layout_edit', 'permissions': [PERMISSION_DOCUMENT_TYPE_EDIT]}
document_type_delete = {'text': _(u'delete'), 'view': 'document_type_delete', 'args': 'document_type.id', 'famfam': 'layout_delete', 'permissions': [PERMISSION_DOCUMENT_TYPE_DELETE]}
document_type_create = {'text': _(u'create document type'), 'view': 'document_type_create', 'famfam': 'layout_add', 'permissions': [PERMISSION_DOCUMENT_TYPE_CREATE]}
document_type_filename_list = {'text': _(u'filenames'), 'view': 'document_type_filename_list', 'args': 'document_type.id', 'famfam': 'database', 'permissions': [PERMISSION_DOCUMENT_VIEW]}
document_type_filename_list = {'text': _(u'filenames'), 'view': 'document_type_filename_list', 'args': 'document_type.id', 'famfam': 'database', 'permissions': [PERMISSION_DOCUMENT_TYPE_VIEW]}
document_type_filename_create = {'text': _(u'add filename to document type'), 'view': 'document_type_filename_create', 'args': 'document_type.id', 'famfam': 'database_add', 'permissions': [PERMISSION_DOCUMENT_TYPE_EDIT]}
document_type_filename_edit = {'text': _(u'edit'), 'view': 'document_type_filename_edit', 'args': 'filename.id', 'famfam': 'database_edit', 'permissions': [PERMISSION_DOCUMENT_TYPE_EDIT]}
document_type_filename_delete = {'text': _(u'delete'), 'view': 'document_type_filename_delete', 'args': 'filename.id', 'famfam': 'database_delete', 'permissions': [PERMISSION_DOCUMENT_TYPE_EDIT]}
@@ -143,8 +131,8 @@ register_links(['setup_document_type_metadata', 'document_type_filename_delete',
register_links(['document_type_filename_create', 'document_type_filename_list', 'document_type_filename_edit', 'document_type_filename_delete'], [document_type_filename_create], menu_name='sidebar')
# Register document links
register_links(Document, [document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations, document_create_siblings])
register_multi_item_links(['document_find_duplicates', 'folder_view', 'index_instance_list', 'document_type_document_list', 'search', 'results', 'document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete])
register_links(Document, [document_view_simple, document_edit, document_print, document_delete, document_download, document_find_duplicates, document_clear_transformations, document_create_siblings])
register_multi_item_links(['document_find_duplicates', 'folder_view', 'index_instance_list', 'document_type_document_list', 'search', 'results', 'document_group_view', 'document_list', 'document_list_recent'], [document_multiple_clear_transformations, document_multiple_delete, document_multiple_download])
# Document Version links
register_links(DocumentVersion, [document_version_revert, document_version_download])
@@ -177,22 +165,10 @@ register_diagnostic('documents', _(u'Documents'), document_missing_list)
register_maintenance_links([document_find_all_duplicates, document_update_page_count, document_clear_image_cache], namespace='documents', title=_(u'documents'))
#def document_exists(document):
# try:
# if document.exists():
# return u'<span class="famfam active famfam-tick"></span>'
# else:
# return u'<span class="famfam active famfam-cross"></span>'
# except Exception, exc:
# return exc
register_model_list_columns(Document, [
{'name':_(u'thumbnail'), 'attribute':
encapsulate(lambda x: document_thumbnail(x))
},
{'name':_(u'tags'), 'attribute':
encapsulate(lambda x: get_tags_inline_widget_simple(x))
},
{'name':_(u'metadata'), 'attribute':
encapsulate(lambda x: get_metadata_string(x))
},
@@ -202,10 +178,10 @@ register_top_menu(
'documents',
link={'famfam': 'page', 'text': _(u'documents'), 'view': 'document_list_recent'},
children_path_regex=[
r'^documents/[^t]', r'^metadata/[^s]', r'comments', r'tags/document', r'grouping/[^s]', r'history/list/for_object/documents'
r'^documents/[^t]', r'^metadata/[^s]', r'comments', r'tags/document', r'grouping/[^s]', r'history/list/for_object/documents',
],
#children_view_regex=[r'upload'],
children_views=['document_folder_list', 'folder_add_document', 'document_index_list', 'upload_version',],
children_view_regex=[r'document_acl', r'smart_link_instance'],
children_views=['document_folder_list', 'folder_add_document', 'document_index_list', 'upload_version', ],
position=1
)
@@ -221,3 +197,15 @@ if (validate_path(document_settings.CACHE_PATH) == False) or (not document_setti
setattr(document_settings, 'CACHE_PATH', tempfile.mkdtemp())
register_setup(document_type_setup)
class_permissions(Document, [
PERMISSION_DOCUMENT_PROPERTIES_EDIT,
PERMISSION_DOCUMENT_EDIT,
PERMISSION_DOCUMENT_VIEW,
PERMISSION_DOCUMENT_DELETE,
PERMISSION_DOCUMENT_DOWNLOAD,
PERMISSION_DOCUMENT_TRANSFORM,
PERMISSION_DOCUMENT_NEW_VERSION,
PERMISSION_DOCUMENT_VERSION_REVERT,
PERMISSION_HISTORY_VIEW
])

View File

@@ -1,8 +1,10 @@
from __future__ import absolute_import
from django.contrib import admin
from metadata.admin import DocumentMetadataInline
from documents.models import (DocumentType, Document,
from .models import (DocumentType, Document,
DocumentTypeFilename, DocumentPage,
DocumentPageTransformation, RecentDocument,
DocumentVersion)
@@ -23,8 +25,8 @@ class DocumentVersionInline(admin.StackedInline):
#inlines = [
# DocumentPageInline,
#]
class DocumentTypeFilenameInline(admin.StackedInline):
model = DocumentTypeFilename
extra = 1

View File

@@ -1,21 +1,22 @@
from __future__ import absolute_import
from django import forms
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
from common.forms import DetailForm
from common.literals import PAGE_SIZE_CHOICES, PAGE_ORIENTATION_CHOICES
from common.conf.settings import DEFAULT_PAPER_SIZE
from common.conf.settings import DEFAULT_PAGE_ORIENTATION
from common.widgets import TextAreaDiv
from common.conf.settings import DEFAULT_PAPER_SIZE, DEFAULT_PAGE_ORIENTATION
from common.widgets import TextAreaDiv
from documents.models import (Document, DocumentType,
from .models import (Document, DocumentType,
DocumentPage, DocumentPageTransformation, DocumentTypeFilename,
DocumentVersion)
from documents.widgets import document_html_widget
from documents.literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES)
from .widgets import document_html_widget
from .literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES)
# Document page forms
class DocumentPageTransformationForm(forms.ModelForm):
@@ -103,7 +104,7 @@ class DocumentPagesCarouselWidget(forms.widgets.Widget):
output.append(u'<div style="white-space:nowrap; overflow: auto;">')
for page in value.pages.all():
output.append(u'<div style="display: inline-block; margin: 5px 10px 10px 10px;">')
output.append(u'<div class="tc">%(page_string)s %(page)s</div>' % {'page_string': ugettext(u'Page'), 'page': page.page_number})
output.append(
@@ -178,24 +179,24 @@ class DocumentForm(forms.ModelForm):
if instance:
self.version_fields(instance)
def version_fields(self, document):
self.fields['version_update'] = forms.ChoiceField(
label=_(u'Version update'),
choices=DocumentVersion.get_version_update_choices(document.latest_version)
)
self.fields['release_level'] = forms.ChoiceField(
label=_(u'Release level'),
choices=RELEASE_LEVEL_CHOICES,
initial=RELEASE_LEVEL_FINAL,
)
self.fields['serial'] = forms.IntegerField(
label=_(u'Release level serial'),
initial=0,
widget=forms.widgets.TextInput(
attrs = {'style': 'width: auto;'}
attrs={'style': 'width: auto;'}
),
)
@@ -208,7 +209,7 @@ class DocumentForm(forms.ModelForm):
new_filename = forms.CharField(
label=_('New document filename'), required=False
)
def clean(self):
cleaned_data = self.cleaned_data
cleaned_data['new_version_data'] = {
@@ -219,7 +220,8 @@ class DocumentForm(forms.ModelForm):
}
# Always return the full collection of cleaned data.
return cleaned_data
return cleaned_data
class DocumentForm_edit(DocumentForm):
"""
@@ -228,7 +230,7 @@ class DocumentForm_edit(DocumentForm):
class Meta:
model = Document
exclude = ('file', 'document_type', 'tags')
def __init__(self, *args, **kwargs):
super(DocumentForm_edit, self).__init__(*args, **kwargs)
self.fields.pop('serial')
@@ -310,3 +312,16 @@ class DocumentTypeFilenameForm_create(forms.ModelForm):
class Meta:
model = DocumentTypeFilename
fields = ('filename',)
class DocumentDownloadForm(forms.Form):
compressed = forms.BooleanField(label=_(u'Compress'), required=False, help_text=_(u'Download the document in the original format or in a compressed manner. This option is selectable only when downloading one document, for multiple documents, the bundle will always be downloads as a compressed file.'))
def __init__(self, *args, **kwargs):
self.document_versions = kwargs.pop('document_versions', None)
super(DocumentDownloadForm, self).__init__(*args, **kwargs)
if len(self.document_versions) > 1:
self.fields['compressed'].initial = True
self.fields['compressed'].widget.attrs.update({'disabled': True})

View File

@@ -5,20 +5,6 @@ PICTURE_ERROR_MEDIUM = u'1297211435_error.png'
PICTURE_UNKNOWN_SMALL = u'1299549572_unknown2.png'
PICTURE_UNKNOWN_MEDIUM = u'1299549805_unknown.png'
PERMISSION_DOCUMENT_CREATE = {'namespace': 'documents', 'name': 'document_create', 'label': _(u'Create documents')}
PERMISSION_DOCUMENT_PROPERTIES_EDIT = {'namespace': 'documents', 'name': 'document_properties_edit', 'label': _(u'Edit document properties')}
PERMISSION_DOCUMENT_EDIT = {'namespace': 'documents', 'name': 'document_edit', 'label': _(u'Edit documents')}
PERMISSION_DOCUMENT_VIEW = {'namespace': 'documents', 'name': 'document_view', 'label': _(u'View documents')}
PERMISSION_DOCUMENT_DELETE = {'namespace': 'documents', 'name': 'document_delete', 'label': _(u'Delete documents')}
PERMISSION_DOCUMENT_DOWNLOAD = {'namespace': 'documents', 'name': 'document_download', 'label': _(u'Download documents')}
PERMISSION_DOCUMENT_TRANSFORM = {'namespace': 'documents', 'name': 'document_transform', 'label': _(u'Transform documents')}
PERMISSION_DOCUMENT_TOOLS = {'namespace': 'documents', 'name': 'document_tools', 'label': _(u'Execute document modifying tools')}
PERMISSION_DOCUMENT_VERSION_REVERT = {'namespace': 'documents', 'name': 'document_version_revert', 'label': _(u'Revert documents to a previous version')}
PERMISSION_DOCUMENT_TYPE_EDIT = {'namespace': 'documents_setup', 'name': 'document_type_edit', 'label': _(u'Edit document types')}
PERMISSION_DOCUMENT_TYPE_DELETE = {'namespace': 'documents_setup', 'name': 'document_type_delete', 'label': _(u'Delete document types')}
PERMISSION_DOCUMENT_TYPE_CREATE = {'namespace': 'documents_setup', 'name': 'document_type_create', 'label': _(u'Create document types')}
HISTORY_DOCUMENT_CREATED = {
'namespace': 'documents', 'name': 'document_created',
'label': _(u'Document creation'),

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,9 @@
from __future__ import absolute_import
from ast import literal_eval
from datetime import datetime
from django.db import models
from documents.conf.settings import RECENT_COUNT
class RecentDocumentManager(models.Manager):
def add_document_for_user(self, user, document):
self.model.objects.filter(user=user, document=document).delete()
new_recent = self.model(user=user, document=document, datetime_accessed=datetime.now())
new_recent.save()
to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:]
for recent_to_delete in to_delete:
recent_to_delete.delete()
class DocumentPageTransformationManager(models.Manager):
def get_for_document_page(self, document_page):

View File

@@ -0,0 +1,165 @@
# encoding: utf-8
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
depends_on = (
('document_signatures', '0002_move_signatures_to_new_app'),
)
def forwards(self, orm):
# Deleting field 'DocumentVersion.signature_file'
db.delete_column('documents_documentversion', 'signature_file')
# Deleting field 'DocumentVersion.signature_state'
db.delete_column('documents_documentversion', 'signature_state')
def backwards(self, orm):
# Adding field 'DocumentVersion.signature_file'
db.add_column('documents_documentversion', 'signature_file', self.gf('django.db.models.fields.files.FileField')(max_length=100, null=True, blank=True), keep_default=False)
# Adding field 'DocumentVersion.signature_state'
db.add_column('documents_documentversion', 'signature_state', self.gf('django.db.models.fields.CharField')(max_length=16, null=True, blank=True), keep_default=False)
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'comments.comment': {
'Meta': {'ordering': "('submit_date',)", 'object_name': 'Comment', 'db_table': "'django_comments'"},
'comment': ('django.db.models.fields.TextField', [], {'max_length': '3000'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'content_type_set_for_comment'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'ip_address': ('django.db.models.fields.IPAddressField', [], {'max_length': '15', 'null': 'True', 'blank': 'True'}),
'is_public': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_removed': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'object_pk': ('django.db.models.fields.TextField', [], {}),
'site': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
'submit_date': ('django.db.models.fields.DateTimeField', [], {'default': 'None'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'comment_comments'", 'null': 'True', 'to': "orm['auth.User']"}),
'user_email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'user_name': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
'user_url': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
},
'documents.document': {
'Meta': {'ordering': "['-date_added']", 'object_name': 'Document'},
'date_added': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']", 'null': 'True', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'uuid': ('django.db.models.fields.CharField', [], {'max_length': '48', 'blank': 'True'})
},
'documents.documentpage': {
'Meta': {'ordering': "['page_number']", 'object_name': 'DocumentPage'},
'content': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_version': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentVersion']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'page_label': ('django.db.models.fields.CharField', [], {'max_length': '32', 'null': 'True', 'blank': 'True'}),
'page_number': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1', 'db_index': 'True'})
},
'documents.documentpagetransformation': {
'Meta': {'ordering': "('order',)", 'object_name': 'DocumentPageTransformation'},
'arguments': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'document_page': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentPage']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'order': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0', 'null': 'True', 'db_index': 'True', 'blank': 'True'}),
'transformation': ('django.db.models.fields.CharField', [], {'max_length': '128'})
},
'documents.documenttype': {
'Meta': {'ordering': "['name']", 'object_name': 'DocumentType'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '32'})
},
'documents.documenttypefilename': {
'Meta': {'ordering': "['filename']", 'object_name': 'DocumentTypeFilename'},
'document_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.DocumentType']"}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'filename': ('django.db.models.fields.CharField', [], {'max_length': '128', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'documents.documentversion': {
'Meta': {'unique_together': "(('document', 'major', 'minor', 'micro', 'release_level', 'serial'),)", 'object_name': 'DocumentVersion'},
'checksum': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
'comment': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
'encoding': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
'filename': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '255', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'major': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
'micro': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'mimetype': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '64'}),
'minor': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'release_level': ('django.db.models.fields.PositiveIntegerField', [], {'default': '1'}),
'serial': ('django.db.models.fields.PositiveIntegerField', [], {'default': '0'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {})
},
'documents.recentdocument': {
'Meta': {'ordering': "('-datetime_accessed',)", 'object_name': 'RecentDocument'},
'datetime_accessed': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'document': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['documents.Document']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"})
},
'sites.site': {
'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'taggit.tag': {
'Meta': {'object_name': 'Tag'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '100', 'db_index': 'True'})
},
'taggit.taggeditem': {
'Meta': {'object_name': 'TaggedItem'},
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_tagged_items'", 'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'object_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'}),
'tag': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'taggit_taggeditem_items'", 'to': "orm['taggit.Tag']"})
}
}
complete_apps = ['documents']

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
import os
import tempfile
import hashlib
@@ -9,17 +11,14 @@ import logging
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from StringIO import StringIO
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.contrib.auth.models import User
from django.contrib.contenttypes import generic
from django.contrib.comments.models import Comment
from django.core.exceptions import ValidationError
from taggit.managers import TaggableManager
from dynamic_search.api import register
from converter.api import get_page_count
from converter.api import get_available_transformations_choices
@@ -29,21 +28,14 @@ from mimetype.api import (get_mimetype, get_icon_file_path,
get_error_icon_file_path)
from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
DEFAULT_PAGE_NUMBER)
from django_gpg.runtime import gpg
from django_gpg.exceptions import GPGVerificationError, GPGDecryptionError
from documents.conf.settings import CHECKSUM_FUNCTION
from documents.conf.settings import UUID_FUNCTION
from documents.conf.settings import STORAGE_BACKEND
from documents.conf.settings import PREVIEW_SIZE
from documents.conf.settings import DISPLAY_SIZE
from documents.conf.settings import CACHE_PATH
from documents.conf.settings import ZOOM_MAX_LEVEL
from documents.conf.settings import ZOOM_MIN_LEVEL
from documents.managers import RecentDocumentManager, \
DocumentPageTransformationManager
from documents.utils import document_save_to_temp_dir
from documents.literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES,
from .conf.settings import RECENT_COUNT
from .conf.settings import (CHECKSUM_FUNCTION, UUID_FUNCTION,
STORAGE_BACKEND, DISPLAY_SIZE, CACHE_PATH,
ZOOM_MAX_LEVEL, ZOOM_MIN_LEVEL)
from .managers import DocumentPageTransformationManager
from .utils import document_save_to_temp_dir
from .literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES,
VERSION_UPDATE_MAJOR, VERSION_UPDATE_MINOR, VERSION_UPDATE_MICRO)
# document image cache name hash function
@@ -78,22 +70,14 @@ class DocumentType(models.Model):
class Document(models.Model):
'''
"""
Defines a single document with it's fields and properties
'''
"""
uuid = models.CharField(max_length=48, blank=True, editable=False)
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True)
description = models.TextField(blank=True, null=True, verbose_name=_(u'description'))
date_added = models.DateTimeField(verbose_name=_(u'added'), db_index=True, editable=False)
tags = TaggableManager()
comments = generic.GenericRelation(
Comment,
content_type_field='content_type',
object_id_field='object_pk'
)
@staticmethod
def clear_image_cache():
for the_file in os.listdir(CACHE_PATH):
@@ -149,7 +133,7 @@ class Document(models.Model):
zoom = ZOOM_MAX_LEVEL
rotation = rotation % 360
try:
file_path = self.get_valid_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version)
except UnknownFileFormat:
@@ -158,7 +142,7 @@ class Document(models.Model):
file_path = get_error_icon_file_path()
except:
file_path = get_error_icon_file_path()
if as_base64:
image = open(file_path, 'r')
out = StringIO()
@@ -175,16 +159,16 @@ class Document(models.Model):
def add_as_recent_document_for_user(self, user):
RecentDocument.objects.add_document_for_user(user, self)
def delete(self, *args, **kwargs):
for version in self.versions.all():
version.delete()
return super(Document, self).delete(*args, **kwargs)
@property
def size(self):
return self.latest_version.size
def new_version(self, file, comment=None, version_update=None, release_level=None, serial=None):
logger.debug('creating new document version')
if version_update:
@@ -193,12 +177,12 @@ class Document(models.Model):
new_version = DocumentVersion(
document=self,
file=file,
major = new_version_dict.get('major'),
minor = new_version_dict.get('minor'),
micro = new_version_dict.get('micro'),
release_level = release_level,
serial = serial,
comment = comment,
major=new_version_dict.get('major'),
minor=new_version_dict.get('minor'),
micro=new_version_dict.get('micro'),
release_level=release_level,
serial=serial,
comment=comment,
)
new_version.save()
else:
@@ -214,20 +198,20 @@ class Document(models.Model):
# Proxy methods
def open(self, *args, **kwargs):
'''
"""
Return a file descriptor to a document's file irrespective of
the storage backend
'''
"""
return self.latest_version.open(*args, **kwargs)
def save_to_file(self, *args, **kwargs):
return self.latest_version.save_to_file(*args, **kwargs)
def exists(self):
'''
Returns a boolean value that indicates if the document's
"""
Returns a boolean value that indicates if the document's
latest version file exists in storage
'''
"""
return self.latest_version.exists()
# Compatibility methods
@@ -242,7 +226,7 @@ class Document(models.Model):
@property
def file_mime_encoding(self):
return self.latest_version.encoding
@property
def file_filename(self):
return self.latest_version.filename
@@ -279,6 +263,10 @@ class Document(models.Model):
def versions(self):
return self.documentversion_set
def rename(self, new_name):
version = self.latest_version
return version.rename(new_name)
def _get_filename(self):
return self.latest_version.filename
@@ -288,24 +276,15 @@ class Document(models.Model):
return version.save()
filename = property(_get_filename, _set_filename)
def add_detached_signature(self, *args, **kwargs):
return self.latest_version.add_detached_signature(*args, **kwargs)
def has_detached_signature(self):
return self.latest_version.has_detached_signature()
def detached_signature(self):
return self.latest_version.detached_signature()
def verify_signature(self):
return self.latest_version.verify_signature()
class DocumentVersion(models.Model):
'''
"""
Model that describes a document version and its properties
'''
"""
_pre_open_hooks = {}
_post_save_hooks = {}
@staticmethod
def get_version_update_choices(document_version):
return (
@@ -313,7 +292,15 @@ class DocumentVersion(models.Model):
(VERSION_UPDATE_MINOR, _(u'Minor %(major)i.%(minor)i, (some updates)') % document_version.get_new_version_dict(VERSION_UPDATE_MINOR)),
(VERSION_UPDATE_MICRO, _(u'Micro %(major)i.%(minor)i.%(micro)i, (fixes)') % document_version.get_new_version_dict(VERSION_UPDATE_MICRO))
)
@classmethod
def register_pre_open_hook(cls, order, func):
cls._pre_open_hooks[order] = func
@classmethod
def register_post_save_hook(cls, order, func):
cls._post_save_hooks[order] = func
document = models.ForeignKey(Document, verbose_name=_(u'document'), editable=False)
major = models.PositiveIntegerField(verbose_name=_(u'mayor'), default=1, editable=False)
minor = models.PositiveIntegerField(verbose_name=_(u'minor'), default=0, editable=False)
@@ -322,16 +309,14 @@ class DocumentVersion(models.Model):
serial = models.PositiveIntegerField(verbose_name=_(u'serial'), default=0, editable=False)
timestamp = models.DateTimeField(verbose_name=_(u'timestamp'), editable=False)
comment = models.TextField(blank=True, verbose_name=_(u'comment'))
# File related fields
file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file'))
mimetype = models.CharField(max_length=64, default='', editable=False)
encoding = models.CharField(max_length=64, default='', editable=False)
filename = models.CharField(max_length=255, default=u'', editable=False, db_index=True)
checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), 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)
class Meta:
unique_together = ('document', 'major', 'minor', 'micro', 'release_level', 'serial')
verbose_name = _(u'document version')
@@ -361,11 +346,11 @@ class DocumentVersion(models.Model):
'minor': self.minor,
'micro': self.micro + 1,
}
def get_formated_version(self):
'''
"""
Return the formatted version information
'''
"""
vers = [u'%i.%i' % (self.major, self.minor), ]
if self.micro:
@@ -379,10 +364,10 @@ class DocumentVersion(models.Model):
return self.documentpage_set
def save(self, *args, **kwargs):
'''
"""
Overloaded save method that updates the document version's checksum,
mimetype, page count and transformation when created
'''
"""
new_document = not self.pk
if not self.pk:
self.timestamp = datetime.datetime.now()
@@ -391,9 +376,11 @@ class DocumentVersion(models.Model):
transformations = kwargs.pop('transformations', None)
super(DocumentVersion, self).save(*args, **kwargs)
for key in sorted(DocumentVersion._post_save_hooks):
DocumentVersion._post_save_hooks[key](self)
if new_document:
#Only do this for new documents
self.update_signed_state(save=False)
self.update_checksum(save=False)
self.update_mimetype(save=False)
self.save()
@@ -402,10 +389,10 @@ class DocumentVersion(models.Model):
self.apply_default_transformations(transformations)
def update_checksum(self, save=True):
'''
"""
Open a document version's file and update the checksum field using the
user provided checksum function
'''
"""
if self.exists():
source = self.open()
self.checksum = unicode(CHECKSUM_FUNCTION(source.read()))
@@ -461,29 +448,17 @@ class DocumentVersion(models.Model):
page_transformation.save()
def revert(self):
'''
"""
Delete the subsequent versions after this one
'''
"""
for version in self.document.versions.filter(timestamp__gt=self.timestamp):
version.delete()
def update_signed_state(self, save=True):
if self.exists():
try:
self.signature_state = gpg.verify_file(self.open()).status
# TODO: give use choice for auto public key fetch?
# OR maybe new config option
except GPGVerificationError:
self.signature_state = None
if save:
self.save()
def update_mimetype(self, save=True):
'''
"""
Read a document verions's file and determine the mimetype by calling the
get_mimetype wrapper
'''
"""
if self.exists():
try:
self.mimetype, self.encoding = get_mimetype(self.open(), self.filename)
@@ -495,37 +470,35 @@ class DocumentVersion(models.Model):
self.save()
def delete(self, *args, **kwargs):
self.file.storage.delete(self.file.path)
self.file.storage.delete(self.file.path)
return super(DocumentVersion, self).delete(*args, **kwargs)
def exists(self):
'''
"""
Returns a boolean value that indicates if the document's file
exists in storage
'''
"""
return self.file.storage.exists(self.file.path)
def open(self, raw=False):
'''
"""
Return a file descriptor to a document version's file irrespective of
the storage backend
'''
if self.signature_state and not raw:
try:
result = gpg.decrypt_file(self.file.storage.open(self.file.path))
# gpg return a string, turn it into a file like object
return StringIO(result.data)
except GPGDecryptionError:
# At least return the original raw content
return self.file.storage.open(self.file.path)
else:
"""
if raw:
return self.file.storage.open(self.file.path)
else:
result = self.file.storage.open(self.file.path)
for key in sorted(DocumentVersion._pre_open_hooks):
result = DocumentVersion._pre_open_hooks[key](result, self)
return result
def save_to_file(self, filepath, buffer_size=1024 * 1024):
'''
"""
Save a copy of the document from the document storage backend
to the local filesystem
'''
"""
input_descriptor = self.open()
output_descriptor = open(filepath, 'wb')
while True:
@@ -538,48 +511,25 @@ class DocumentVersion(models.Model):
output_descriptor.close()
input_descriptor.close()
return filepath
@property
def size(self):
if self.exists():
return self.file.storage.size(self.file.path)
else:
return None
def add_detached_signature(self, detached_signature):
if not self.signature_state:
self.signature_file = detached_signature
self.save()
else:
raise Exception('document already has an embedded signature')
def has_detached_signature(self):
if self.signature_file:
return self.signature_file.storage.exists(self.signature_file.path)
else:
return False
def detached_signature(self):
return self.signature_file.storage.open(self.signature_file.path)
def verify_signature(self):
try:
if self.has_detached_signature():
logger.debug('has detached signature')
signature = gpg.verify_w_retry(self.open(), self.detached_signature())
else:
signature = gpg.verify_w_retry(self.open(raw=True))
except GPGVerificationError:
signature = None
return signature
def rename(self, new_name):
name, extension = os.path.splitext(self.filename)
self.filename = u''.join([new_name, extension])
self.save()
class DocumentTypeFilename(models.Model):
'''
"""
List of filenames available to a specific document type for the
quick rename functionality
'''
"""
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
filename = models.CharField(max_length=128, verbose_name=_(u'filename'), db_index=True)
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
@@ -594,13 +544,10 @@ class DocumentTypeFilename(models.Model):
class DocumentPage(models.Model):
'''
"""
Model that describes a document version page including it's content
'''
# New parent field
"""
document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'))
# Unchanged fields
content = models.TextField(blank=True, null=True, verbose_name=_(u'content'))
page_label = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u'page label'))
page_number = models.PositiveIntegerField(default=1, editable=False, verbose_name=_(u'page number'), db_index=True)
@@ -627,7 +574,7 @@ class DocumentPage(models.Model):
@property
def siblings(self):
return DocumentPage.objects.filter(document_version=self.document_version)
# Compatibility methods
@property
def document(self):
@@ -675,6 +622,23 @@ class DocumentPageTransformation(models.Model):
verbose_name_plural = _(u'document page transformations')
class RecentDocumentManager(models.Manager):
def add_document_for_user(self, user, document):
if user.is_authenticated():
self.model.objects.filter(user=user, document=document).delete()
new_recent = self.model(user=user, document=document, datetime_accessed=datetime.datetime.now())
new_recent.save()
to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:]
for recent_to_delete in to_delete:
recent_to_delete.delete()
def get_for_user(self, user):
if user.is_authenticated():
return Document.objects.filter(recentdocument__user=user)
else:
return []
class RecentDocument(models.Model):
"""
Keeps a list of the n most recent accessed or created document for

View File

@@ -0,0 +1,25 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from permissions.models import PermissionNamespace, Permission
document_namespace = PermissionNamespace('documents', _(u'Documents'))
PERMISSION_DOCUMENT_CREATE = Permission.objects.register(document_namespace, 'document_create', _(u'Create documents'))
PERMISSION_DOCUMENT_PROPERTIES_EDIT = Permission.objects.register(document_namespace, 'document_properties_edit', _(u'Edit document properties'))
PERMISSION_DOCUMENT_EDIT = Permission.objects.register(document_namespace, 'document_edit', _(u'Edit documents'))
PERMISSION_DOCUMENT_VIEW = Permission.objects.register(document_namespace, 'document_view', _(u'View documents'))
PERMISSION_DOCUMENT_DELETE = Permission.objects.register(document_namespace, 'document_delete', _(u'Delete documents'))
PERMISSION_DOCUMENT_DOWNLOAD = Permission.objects.register(document_namespace, 'document_download', _(u'Download documents'))
PERMISSION_DOCUMENT_TRANSFORM = Permission.objects.register(document_namespace, 'document_transform', _(u'Transform documents'))
PERMISSION_DOCUMENT_TOOLS = Permission.objects.register(document_namespace, 'document_tools', _(u'Execute document modifying tools'))
PERMISSION_DOCUMENT_VERSION_REVERT = Permission.objects.register(document_namespace, 'document_version_revert', _(u'Revert documents to a previous version'))
PERMISSION_DOCUMENT_NEW_VERSION = Permission.objects.register(document_namespace, 'document_new_version', _(u'Create new document versions'))
documents_setup_namespace = PermissionNamespace('documents_setup', _(u'Documents setup'))
PERMISSION_DOCUMENT_TYPE_VIEW = Permission.objects.register(documents_setup_namespace, 'document_type_view', _(u'View document types'))
PERMISSION_DOCUMENT_TYPE_EDIT = Permission.objects.register(documents_setup_namespace, 'document_type_edit', _(u'Edit document types'))
PERMISSION_DOCUMENT_TYPE_DELETE = Permission.objects.register(documents_setup_namespace, 'document_type_delete', _(u'Delete document types'))
PERMISSION_DOCUMENT_TYPE_CREATE = Permission.objects.register(documents_setup_namespace, 'document_type_create', _(u'Create document types'))

View File

@@ -1,10 +1,12 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.db.models import Avg, Count, Min, Max
from common.utils import pretty_size, pretty_size_10
from documents.conf.settings import STORAGE_BACKEND
from documents.models import Document, DocumentType, DocumentPage, DocumentVersion
from django.db.models import Avg, Count, Min, Max
from .conf.settings import STORAGE_BACKEND
from .models import Document, DocumentType, DocumentPage, DocumentVersion
def get_used_size(path, file_list):

View File

@@ -1,23 +1,85 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
from __future__ import absolute_import
Replace these with more appropriate tests for your application.
"""
import os
from django.test import TestCase
from django.utils import unittest
from django.conf import settings
from django.core.files.base import File
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
from django_gpg.api import SIGNATURE_STATE_VALID
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
from .models import Document, DocumentType
from .literals import VERSION_UPDATE_MAJOR, RELEASE_LEVEL_FINAL
>>> 1 + 1 == 2
True
"""}
class DocumentTestCase(unittest.TestCase):
def setUp(self):
self.document_type = DocumentType(name='test doc type')
self.document_type.save()
self.document = Document(
document_type=self.document_type,
description='description',
)
self.document.save()
#return File(file(self.filepath, 'rb'), name=self.filename)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf'))
new_version = self.document.new_version(file=File(file_object, name='mayan_11_1.pdf'))
file_object.close()
def runTest(self):
self.failUnlessEqual(self.document_type.name, 'test doc type')
self.failUnlessEqual(self.document.exists(), True)
self.failUnlessEqual(self.document.size, 272213)
self.failUnlessEqual(self.document.file_mimetype, 'application/pdf')
self.failUnlessEqual(self.document.file_mime_encoding, 'binary')
self.failUnlessEqual(self.document.file_filename, 'mayan_11_1.pdf')
self.failUnlessEqual(self.document.checksum, 'c637ffab6b8bb026ed3784afdb07663fddc60099853fae2be93890852a69ecf3')
self.failUnlessEqual(self.document.page_count, 47)
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '1.0')
self.failUnlessEqual(self.document.has_detached_signature(), False)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf.gpg'))
new_version_data = {
'comment': 'test comment 1',
'version_update': VERSION_UPDATE_MAJOR,
'release_level': RELEASE_LEVEL_FINAL,
'serial': 0,
}
new_version = self.document.new_version(file=File(file_object, name='mayan_11_1.pdf.gpg'), **new_version_data)
file_object.close()
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '2.0')
self.failUnlessEqual(self.document.has_detached_signature(), False)
self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID)
new_version_data = {
'comment': 'test comment 2',
'version_update': VERSION_UPDATE_MAJOR,
'release_level': RELEASE_LEVEL_FINAL,
'serial': 0,
}
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf'))
new_version = self.document.new_version(file=File(file_object), **new_version_data)
file_object.close()
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '3.0')
#GPGVerificationError
self.failUnlessEqual(self.document.verify_signature(), None)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf.sig'), 'rb')
new_version = self.document.add_detached_signature(File(file_object))
file_object.close()
self.failUnlessEqual(self.document.has_detached_signature(), True)
self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID)
def tearDown(self):
self.document.delete()

View File

@@ -1,10 +1,9 @@
from __future__ import absolute_import
from django.conf.urls.defaults import patterns, url
from documents.conf.settings import PREVIEW_SIZE
from documents.conf.settings import PRINT_SIZE
from documents.conf.settings import THUMBNAIL_SIZE
from documents.conf.settings import DISPLAY_SIZE
from documents.conf.settings import MULTIPAGE_PREVIEW_SIZE
from .conf.settings import (PREVIEW_SIZE, PRINT_SIZE, THUMBNAIL_SIZE,
DISPLAY_SIZE, MULTIPAGE_PREVIEW_SIZE)
urlpatterns = patterns('documents.views',
url(r'^list/$', 'document_list', (), 'document_list'),
@@ -30,10 +29,11 @@ urlpatterns = patterns('documents.views',
url(r'^(?P<document_id>\d+)/display/thumbnail/base64/$', 'get_document_image', {'size': THUMBNAIL_SIZE, 'base64_version': True}, 'document_thumbnail_base64'),
url(r'^(?P<document_id>\d+)/download/$', 'document_download', (), 'document_download'),
url(r'^multiple/download/$', 'document_multiple_download', (), 'document_multiple_download'),
url(r'^(?P<document_id>\d+)/create/siblings/$', 'document_create_siblings', (), 'document_create_siblings'),
url(r'^(?P<document_id>\d+)/find_duplicates/$', 'document_find_duplicates', (), 'document_find_duplicates'),
url(r'^(?P<document_id>\d+)/clear_transformations/$', 'document_clear_transformations', (), 'document_clear_transformations'),
url(r'^(?P<document_pk>\d+)/version/all/$', 'document_version_list', (), 'document_version_list'),
url(r'^document/version/(?P<document_version_pk>\d+)/download/$', 'document_download', (), 'document_version_download'),
url(r'^document/version/(?P<document_version_pk>\d+)/revert/$', 'document_version_revert', (), 'document_version_revert'),

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,14 @@
from __future__ import absolute_import
from django.utils.safestring import mark_safe
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.utils.http import urlencode
from converter.literals import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \
DEFAULT_PAGE_NUMBER
from converter.exceptions import UnknownFileFormat, UnkownConvertError
from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
DEFAULT_PAGE_NUMBER)
from mimetype.api import get_error_icon_url
from documents.conf.settings import DISPLAY_SIZE
def document_thumbnail(document):
@@ -22,7 +21,7 @@ def document_link(document):
def document_html_widget(document, view='document_thumbnail', click_view=None, page=DEFAULT_PAGE_NUMBER, zoom=DEFAULT_ZOOM_LEVEL, rotation=DEFAULT_ROTATION, gallery_name=None, fancybox_class='fancybox', version=None):
result = []
alt_text = _(u'document page image')
if not version:
@@ -39,13 +38,13 @@ def document_html_widget(document, view='document_thumbnail', click_view=None, p
gallery_template = u'rel="%s"' % gallery_name
else:
gallery_template = u''
query_string = urlencode(query_dict)
preview_view = u'%s?%s' % (reverse(view, args=[document.pk]), query_string)
plain_template = []
plain_template.append(u'<img src="%s" alt="%s" />' % (preview_view, alt_text))
result.append(u'<div class="tc" id="document-%d-%d">' % (document.pk, page if page else 1))
if click_view:
@@ -53,7 +52,7 @@ def document_html_widget(document, view='document_thumbnail', click_view=None, p
result.append(u'<img class="thin_border lazy-load" data-href="%s" src="%simages/ajax-loader.gif" alt="%s" />' % (preview_view, settings.STATIC_URL, alt_text))
result.append(u'<noscript><img style="border: 1px solid black;" src="%s" alt="%s" /></noscript>' % (preview_view, alt_text))
if click_view:
if click_view:
result.append(u'</a>')
result.append(u'</div>')

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
@@ -7,7 +9,7 @@ from common.utils import urlquote
from metadata.forms import MetadataSelectionForm, MetadataFormSet
from documents.forms import DocumentTypeSelectForm
from .forms import DocumentTypeSelectForm
class DocumentCreateWizard(BoundFormWizard):