Merge branch 'feature/pep8_cleanups' into development

This commit is contained in:
Roberto Rosario
2012-01-19 12:04:16 -04:00
113 changed files with 778 additions and 1043 deletions
+1 -1
View File
@@ -7,7 +7,7 @@ from project_setup.api import register_setup
from .classes import (AccessHolder, AccessObjectClass, ClassAccessHolder, from .classes import (AccessHolder, AccessObjectClass, ClassAccessHolder,
AccessObject) AccessObject)
from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL, from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL,
ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL) ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL)
+1 -3
View File
@@ -1,8 +1,6 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.contrib import admin from django.contrib import admin
from django.contrib.contenttypes import generic
from django.contrib.contenttypes.models import ContentType
from .models import AccessEntry from .models import AccessEntry
@@ -21,5 +19,5 @@ class AccessEntryAdmin(admin.ModelAdmin):
list_display = ('pk', 'holder_object', 'permission', 'content_object') list_display = ('pk', 'holder_object', 'permission', 'content_object')
list_display_links = ('pk',) list_display_links = ('pk',)
model = AccessEntry model = AccessEntry
admin.site.register(AccessEntry, AccessEntryAdmin) admin.site.register(AccessEntry, AccessEntryAdmin)
+21 -22
View File
@@ -4,21 +4,21 @@ import logging
import sys import sys
import types import types
from django.db import models
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.template.defaultfilters import capfirst from django.template.defaultfilters import capfirst
from django.core.exceptions import ObjectDoesNotExist
from common.models import AnonymousUserSingleton from common.models import AnonymousUserSingleton
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
_cache = {} _cache = {}
class EncapsulatedObject(object): class EncapsulatedObject(object):
source_object_name = u'source_object' source_object_name = u'source_object'
@classmethod @classmethod
def object_key(cls, app_label=None, model=None, pk=None): def object_key(cls, app_label=None, model=None, pk=None):
if pk: if pk:
@@ -31,21 +31,20 @@ class EncapsulatedObject(object):
if hasattr(value, 'contribute_to_class'): if hasattr(value, 'contribute_to_class'):
value.contribute_to_class(cls, name) value.contribute_to_class(cls, name)
else: else:
setattr(cls, name, value) setattr(cls, name, value)
@classmethod @classmethod
def set_source_object_name(cls, new_name): def set_source_object_name(cls, new_name):
cls.source_object_name = new_name cls.source_object_name = new_name
#@classmethod #@classmethod
#def encapsulate_list(cls, source_object=None, app_label=None, model=None, pk=None): #def encapsulate_list(cls, source_object=None, app_label=None, model=None, pk=None):
@classmethod @classmethod
def encapsulate(cls, source_object): def encapsulate(cls, source_object):
source_object = AnonymousUserSingleton.objects.passthru_check(source_object) source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
content_type = ContentType.objects.get_for_model(source_object) content_type = ContentType.objects.get_for_model(source_object)
if hasattr(source_object, 'pk'): if hasattr(source_object, 'pk'):
# Object # Object
object_key = cls.object_key(content_type.app_label, content_type.model, source_object.pk) object_key = cls.object_key(content_type.app_label, content_type.model, source_object.pk)
@@ -68,9 +67,9 @@ class EncapsulatedObject(object):
elif len(elements) == 2: elif len(elements) == 2:
app_label, model = elements[0], elements[1] app_label, model = elements[0], elements[1]
pk = None pk = None
object_key = cls.object_key(*elements) object_key = cls.object_key(*elements)
try: try:
return _cache[object_key] return _cache[object_key]
except KeyError: except KeyError:
@@ -91,9 +90,9 @@ class EncapsulatedObject(object):
raise ObjectDoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name) raise ObjectDoesNotExist("%s matching query does not exist." % source_object_model_class._meta.object_name)
else: else:
source_object = source_object_model_class source_object = source_object_model_class
return cls.encapsulate(source_object) return cls.encapsulate(source_object)
def __init__(self, source_object): def __init__(self, source_object):
self.content_type = ContentType.objects.get_for_model(source_object) self.content_type = ContentType.objects.get_for_model(source_object)
self.ct_fullname = '%s.%s' % (self.content_type.app_label, self.content_type.name) self.ct_fullname = '%s.%s' % (self.content_type.app_label, self.content_type.name)
@@ -102,15 +101,15 @@ class EncapsulatedObject(object):
# Class # Class
self.gid = '%s.%s' % (self.content_type.app_label, self.content_type.model) self.gid = '%s.%s' % (self.content_type.app_label, self.content_type.model)
else: else:
# Object # Object
self.gid = '%s.%s.%s' % (self.content_type.app_label, self.content_type.model, source_object.pk) self.gid = '%s.%s.%s' % (self.content_type.app_label, self.content_type.model, source_object.pk)
setattr(self, self.__class__.source_object_name, source_object) setattr(self, self.__class__.source_object_name, source_object)
def __unicode__(self): def __unicode__(self):
if isinstance(self.source_object, ModelBase): if isinstance(self.source_object, ModelBase):
return capfirst(unicode(self.source_object._meta.verbose_name_plural)) return capfirst(unicode(self.source_object._meta.verbose_name_plural))
elif self.ct_fullname == 'auth.user': elif self.ct_fullname == 'auth.user':
return u'%s %s' % (self.source_object._meta.verbose_name, self.source_object.get_full_name()) return u'%s %s' % (self.source_object._meta.verbose_name, self.source_object.get_full_name())
else: else:
@@ -118,19 +117,19 @@ class EncapsulatedObject(object):
def __repr__(self): def __repr__(self):
return self.__unicode__() return self.__unicode__()
@property @property
def source_object(self): def source_object(self):
return getattr(self, self.__class__.source_object_name, None) return getattr(self, self.__class__.source_object_name, None)
class AccessHolder(EncapsulatedObject): class AccessHolder(EncapsulatedObject):
source_object_name = u'holder_object' source_object_name = u'holder_object'
class AccessObject(EncapsulatedObject): class AccessObject(EncapsulatedObject):
source_object_name = u'obj' source_object_name = u'obj'
class AccessObjectClass(EncapsulatedObject): class AccessObjectClass(EncapsulatedObject):
source_object_name = u'cls' source_object_name = u'cls'
+7 -6
View File
@@ -4,8 +4,8 @@ from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from permissions.models import Permission, Role from permissions.models import Role
from common.utils import generate_choices_w_labels, encapsulate, get_object_name from common.utils import get_object_name
from common.models import AnonymousUserSingleton from common.models import AnonymousUserSingleton
from .classes import AccessHolder from .classes import AccessHolder
@@ -14,11 +14,12 @@ from .classes import AccessHolder
def _as_choice_list(holders): def _as_choice_list(holders):
return sorted([(AccessHolder.encapsulate(holder).gid, get_object_name(holder, display_object_type=False)) for holder in holders], key=lambda x: x[1]) return sorted([(AccessHolder.encapsulate(holder).gid, get_object_name(holder, display_object_type=False)) for holder in holders], key=lambda x: x[1])
class HolderSelectionForm(forms.Form): class HolderSelectionForm(forms.Form):
holder_gid = forms.ChoiceField( holder_gid = forms.ChoiceField(
label=_(u'New holder') label=_(u'New holder')
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
current_holders = kwargs.pop('current_holders', []) current_holders = kwargs.pop('current_holders', [])
if current_holders: if current_holders:
@@ -29,14 +30,14 @@ class HolderSelectionForm(forms.Form):
users = set(User.objects.filter(is_active=True)) - set(staff_users) - set(super_users) - set(current_holders) users = set(User.objects.filter(is_active=True)) - set(staff_users) - set(super_users) - set(current_holders)
roles = set(Role.objects.all()) - set(current_holders) roles = set(Role.objects.all()) - set(current_holders)
groups = set(Group.objects.all()) - set(current_holders) groups = set(Group.objects.all()) - set(current_holders)
non_holder_list = [] non_holder_list = []
if users: if users:
non_holder_list.append((_(u'Users'), _as_choice_list(list(users)))) non_holder_list.append((_(u'Users'), _as_choice_list(list(users))))
if groups: if groups:
non_holder_list.append((_(u'Groups'), _as_choice_list(list(groups)))) non_holder_list.append((_(u'Groups'), _as_choice_list(list(groups))))
if roles: if roles:
non_holder_list.append((_(u'Roles'), _as_choice_list(list(roles)))) non_holder_list.append((_(u'Roles'), _as_choice_list(list(roles))))
+62 -33
View File
@@ -8,8 +8,10 @@ from django.utils.translation import ugettext
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from common.models import AnonymousUserSingleton from common.models import AnonymousUserSingleton
from permissions.models import Permission
from .classes import EncapsulatedObject, AccessHolder, ClassAccessHolder from .classes import EncapsulatedObject, AccessHolder, ClassAccessHolder
@@ -17,19 +19,23 @@ logger = logging.getLogger(__name__)
class AccessEntryManager(models.Manager): class AccessEntryManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permissions, an actor
and an object
"""
def source_object(self, obj): def source_object(self, obj):
if isinstance(obj, EncapsulatedObject): if isinstance(obj, EncapsulatedObject):
return obj.source_object return obj.source_object
else: else:
return obj return obj
def grant(self, permission, actor, obj): def grant(self, permission, actor, obj):
''' """
Grant a permission (what), (to) an actor, (on) a specific object Grant a permission (what), (to) an actor, (on) a specific object
''' """
obj = self.source_object(obj) obj = self.source_object(obj)
actor = self.source_object(actor) actor = self.source_object(actor)
access_entry, created = self.model.objects.get_or_create( access_entry, created = self.model.objects.get_or_create(
permission=permission, permission=permission,
holder_type=ContentType.objects.get_for_model(actor), holder_type=ContentType.objects.get_for_model(actor),
@@ -40,9 +46,9 @@ class AccessEntryManager(models.Manager):
return created return created
def revoke(self, permission, actor, obj): def revoke(self, permission, actor, obj):
''' """
Revoke a permission (what), (from) an actor, (on) a specific object Revoke a permission (what), (from) an actor, (on) a specific object
''' """
obj = self.source_object(obj) obj = self.source_object(obj)
actor = self.source_object(actor) actor = self.source_object(actor)
@@ -57,12 +63,15 @@ class AccessEntryManager(models.Manager):
access_entry.delete() access_entry.delete()
return True return True
except self.model.DoesNotExist: except self.model.DoesNotExist:
return False return False
def has_access(self, permission, actor, obj): def has_access(self, permission, actor, obj):
"""
Returns whether an actor has a specific permission for an object
"""
obj = self.source_object(obj) obj = self.source_object(obj)
actor = self.source_object(actor) actor = self.source_object(actor)
if isinstance(actor, User): if isinstance(actor, User):
if actor.is_superuser or actor.is_staff: if actor.is_superuser or actor.is_staff:
return True return True
@@ -70,18 +79,20 @@ class AccessEntryManager(models.Manager):
actor = AnonymousUserSingleton.objects.passthru_check(actor) actor = AnonymousUserSingleton.objects.passthru_check(actor)
try: try:
access_entry = self.model.objects.get( self.model.objects.get(
permission=permission.get_stored_permission(), permission=permission.get_stored_permission(),
holder_type=ContentType.objects.get_for_model(actor), holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk, holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(obj), content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk object_id=obj.pk
) )
return True
except self.model.DoesNotExist: except self.model.DoesNotExist:
return False return False
else:
return True
def check_access(self, permission, actor, obj): def check_access(self, permission, actor, obj):
# TODO: Merge with has_access
obj = self.source_object(obj) obj = self.source_object(obj)
actor = self.source_object(actor) actor = self.source_object(actor)
@@ -89,8 +100,11 @@ class AccessEntryManager(models.Manager):
return True return True
else: else:
raise PermissionDenied(ugettext(u'Insufficient access.')) raise PermissionDenied(ugettext(u'Insufficient access.'))
def check_accesses(self, permission_list, actor, obj): def check_accesses(self, permission_list, actor, obj):
"""
Returns whether an actor has at least one of a list of permissions for an object
"""
obj = self.source_object(obj) obj = self.source_object(obj)
actor = self.source_object(actor) actor = self.source_object(actor)
for permission in permission_list: for permission in permission_list:
@@ -101,7 +115,7 @@ class AccessEntryManager(models.Manager):
def get_allowed_class_objects(self, permission, actor, cls, related=None): def get_allowed_class_objects(self, permission, actor, cls, related=None):
logger.debug('related: %s' % related) logger.debug('related: %s' % related)
actor = AnonymousUserSingleton.objects.passthru_check(actor) actor = AnonymousUserSingleton.objects.passthru_check(actor)
actor_type = ContentType.objects.get_for_model(actor) actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(cls) content_type = ContentType.objects.get_for_model(cls)
@@ -122,22 +136,26 @@ class AccessEntryManager(models.Manager):
def get_new_holder_url(self, obj): def get_new_holder_url(self, obj):
content_type = ContentType.objects.get_for_model(obj) content_type = ContentType.objects.get_for_model(obj)
return reverse('acl_new_holder_for', args=[content_type.app_label, content_type.model, obj.pk]) return reverse('acl_new_holder_for', args=[content_type.app_label, content_type.model, obj.pk])
def get_holders_for(self, obj): def get_holders_for(self, obj):
content_type = ContentType.objects.get_for_model(obj) content_type = ContentType.objects.get_for_model(obj)
holder_list = [] holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk): for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk):
entry = AccessHolder.encapsulate(access_entry.holder_object) entry = AccessHolder.encapsulate(access_entry.holder_object)
if entry not in holder_list: if entry not in holder_list:
holder_list.append(entry) holder_list.append(entry)
return holder_list return holder_list
def get_holder_permissions_for(self, obj, actor): def get_holder_permissions_for(self, obj, actor):
"""
Returns a list of actors that hold at least one permission for
a specific object
"""
logger.debug('obj: %s' % obj) logger.debug('obj: %s' % obj)
logger.debug('actor: %s' % actor) logger.debug('actor: %s' % actor)
if isinstance(actor, User): if isinstance(actor, User):
if actor.is_superuser or actor.is_staff: if actor.is_superuser or actor.is_staff:
return Permission.objects.all() return Permission.objects.all()
@@ -147,13 +165,17 @@ class AccessEntryManager(models.Manager):
return (access.permission for access in self.model.objects.filter(content_type=content_type, object_id=obj.pk, holder_type=actor_type, holder_id=actor.pk)) return (access.permission for access in self.model.objects.filter(content_type=content_type, object_id=obj.pk, holder_type=actor_type, holder_id=actor.pk))
def filter_objects_by_access(self, permission, actor, object_list, exception_on_empty=False, related=None): def filter_objects_by_access(self, permission, actor, object_list, exception_on_empty=False, related=None):
"""
Filter a list of objects or a QuerySet elements depending on
whether the actor holds the specified permission
"""
logger.debug('exception_on_empty: %s' % exception_on_empty) logger.debug('exception_on_empty: %s' % exception_on_empty)
logger.debug('object_list: %s' % object_list) logger.debug('object_list: %s' % object_list)
if isinstance(actor, User): if isinstance(actor, User):
if actor.is_superuser or actor.is_staff: if actor.is_superuser or actor.is_staff:
return object_list return object_list
try: try:
if object_list.count() == 0: if object_list.count() == 0:
return object_list return object_list
@@ -161,15 +183,15 @@ class AccessEntryManager(models.Manager):
# object_list is not a queryset # object_list is not a queryset
if len(object_list) == 0: if len(object_list) == 0:
return object_list return object_list
try: try:
# Try to process as a QuerySet # Try to process as a QuerySet
qs = object_list.filter(pk__in=[obj.pk for obj in self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)]) qs = object_list.filter(pk__in=[obj.pk for obj in self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)])
logger.debug('qs: %s' % qs) logger.debug('qs: %s' % qs)
if qs.count() == 0 and exception_on_empty == True: if qs.count() == 0 and exception_on_empty == True:
raise PermissionDenied raise PermissionDenied
return qs return qs
except AttributeError: except AttributeError:
# Fallback to a filtered list # Fallback to a filtered list
@@ -182,6 +204,12 @@ class AccessEntryManager(models.Manager):
class DefaultAccessEntryManager(models.Manager): class DefaultAccessEntryManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permission, an actor
and a class or content type. This model keeps track of the access
control lists that will be added when an instance of the recorded
content type is created.
"""
def get_holders_for(self, cls): def get_holders_for(self, cls):
if isinstance(cls, EncapsulatedObject): if isinstance(cls, EncapsulatedObject):
cls = cls.source_object cls = cls.source_object
@@ -190,32 +218,33 @@ class DefaultAccessEntryManager(models.Manager):
holder_list = [] holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type): for access_entry in self.model.objects.filter(content_type=content_type):
entry = ClassAccessHolder.encapsulate(access_entry.holder_object) entry = ClassAccessHolder.encapsulate(access_entry.holder_object)
if entry not in holder_list: if entry not in holder_list:
holder_list.append(entry) holder_list.append(entry)
return holder_list return holder_list
def has_access(self, permission, actor, cls): def has_access(self, permission, actor, cls):
if isinstance(actor, User): if isinstance(actor, User):
if actor.is_superuser or actor.is_staff: if actor.is_superuser or actor.is_staff:
return True return True
try: try:
access_entry = self.model.objects.get( self.model.objects.get(
permission=permission.get_stored_permission(), permission=permission.get_stored_permission(),
holder_type=ContentType.objects.get_for_model(actor), holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk, holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls), content_type=ContentType.objects.get_for_model(cls),
) )
return True
except self.model.DoesNotExist: except self.model.DoesNotExist:
return False return False
else:
return True
def grant(self, permission, actor, cls): def grant(self, permission, actor, cls):
''' """
Grant a permission (what), (to) an actor, (on) a specific class Grant a permission (what), (to) an actor, (on) a specific class
''' """
access_entry, created = self.model.objects.get_or_create( access_entry, created = self.model.objects.get_or_create(
permission=permission, permission=permission,
holder_type=ContentType.objects.get_for_model(actor), holder_type=ContentType.objects.get_for_model(actor),
@@ -225,9 +254,9 @@ class DefaultAccessEntryManager(models.Manager):
return created return created
def revoke(self, permission, actor, cls): def revoke(self, permission, actor, cls):
''' """
Revoke a permission (what), (from) an actor, (on) a specific class Revoke a permission (what), (from) an actor, (on) a specific class
''' """
try: try:
access_entry = self.model.objects.get( access_entry = self.model.objects.get(
permission=permission, permission=permission,
@@ -238,13 +267,13 @@ class DefaultAccessEntryManager(models.Manager):
access_entry.delete() access_entry.delete()
return True return True
except self.model.DoesNotExist: except self.model.DoesNotExist:
return False return False
def get_holder_permissions_for(self, cls, actor): def get_holder_permissions_for(self, cls, actor):
if isinstance(actor, User): if isinstance(actor, User):
if actor.is_superuser or actor.is_staff: if actor.is_superuser or actor.is_staff:
return Permission.objects.all() return Permission.objects.all()
actor_type = ContentType.objects.get_for_model(actor) actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(cls) content_type = ContentType.objects.get_for_model(cls)
return [access.permission for access in self.model.objects.filter(content_type=content_type, holder_type=actor_type, holder_id=actor.pk)] return [access.permission for access in self.model.objects.filter(content_type=content_type, holder_type=actor_type, holder_id=actor.pk)]
+6 -8
View File
@@ -8,9 +8,7 @@ from django.utils.translation import ugettext
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import get_object_or_404
from permissions.models import StoredPermission from permissions.models import StoredPermission
@@ -20,11 +18,11 @@ from .api import get_classes
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class AccessEntry(models.Model): class AccessEntry(models.Model):
''' """
Model that hold the permission, object, actor relationship Model that hold the permission, object, actor relationship
''' """
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission')) permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey( holder_type = models.ForeignKey(
@@ -59,14 +57,14 @@ class AccessEntry(models.Model):
class DefaultAccessEntry(models.Model): class DefaultAccessEntry(models.Model):
''' """
Model that holds the permission, class, actor relationship, that will Model that holds the permission, class, actor relationship, that will
be added upon the creation of an instance of said class be added upon the creation of an instance of said class
''' """
@classmethod @classmethod
def get_classes(cls): def get_classes(cls):
return [AccessObjectClass.encapsulate(cls) for cls in get_classes()] return [AccessObjectClass.encapsulate(cls) for cls in get_classes()]
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission')) permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey( holder_type = models.ForeignKey(
+2 -2
View File
@@ -3,7 +3,7 @@ import logging
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.template import (TemplateSyntaxError, Library, from django.template import (TemplateSyntaxError, Library,
Node, Variable, VariableDoesNotExist) Node, Variable, VariableDoesNotExist)
from acls.models import AccessEntry from acls.models import AccessEntry
@@ -33,7 +33,7 @@ class CheckAccessNode(Node):
context[u'access'] = False context[u'access'] = False
logger.debug('no obj, access False') logger.debug('no obj, access False')
return u'' return u''
if not permission_list: if not permission_list:
# There is no permissions list to check against which means # There is no permissions list to check against which means
# this link is available for all # this link is available for all
+2 -2
View File
@@ -5,13 +5,13 @@ urlpatterns = patterns('acls.views',
url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', (), 'acl_list'), url(r'^list_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_list', (), 'acl_list'),
url(r'^details/(?P<access_object_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_detail', (), 'acl_detail'), url(r'^details/(?P<access_object_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_detail', (), 'acl_detail'),
url(r'^holder/new/(?P<access_object_gid>[.\w]+)/$', 'acl_holder_new', (), 'acl_holder_new'), url(r'^holder/new/(?P<access_object_gid>[.\w]+)/$', 'acl_holder_new', (), 'acl_holder_new'),
url(r'^multiple/grant/$', 'acl_grant', (), 'acl_multiple_grant'), url(r'^multiple/grant/$', 'acl_grant', (), 'acl_multiple_grant'),
url(r'^multiple/revoke/$', 'acl_revoke', (), 'acl_multiple_revoke'), url(r'^multiple/revoke/$', 'acl_revoke', (), 'acl_multiple_revoke'),
url(r'^class/$', 'acl_setup_valid_classes', (), 'acl_setup_valid_classes'), url(r'^class/$', 'acl_setup_valid_classes', (), 'acl_setup_valid_classes'),
url(r'^class/details/(?P<access_object_class_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_class_acl_detail', (), 'acl_class_acl_detail'), url(r'^class/details/(?P<access_object_class_gid>[.\w]+)/holder/(?P<holder_object_gid>[.\w]+)/$', 'acl_class_acl_detail', (), 'acl_class_acl_detail'),
url(r'^class/list_for/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_acl_list', (), 'acl_class_acl_list'), url(r'^class/list_for/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_acl_list', (), 'acl_class_acl_list'),
url(r'^class/holder/new/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_new_holder_for', (), 'acl_class_new_holder_for'), url(r'^class/holder/new/(?P<access_object_class_gid>[.\w]+)/$', 'acl_class_new_holder_for', (), 'acl_class_new_holder_for'),
url(r'^class/multiple/grant/$', 'acl_class_multiple_grant', (), 'acl_class_multiple_grant'), url(r'^class/multiple/grant/$', 'acl_class_multiple_grant', (), 'acl_class_multiple_grant'),
+51 -56
View File
@@ -1,43 +1,39 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
import operator
import itertools
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect, Http404 from django.http import HttpResponseRedirect, Http404
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.contrib import messages from django.contrib import messages
from django.views.generic.list_detail import object_list
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User, Group
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.simplejson import loads from django.utils.simplejson import loads
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.utils.http import urlencode from django.utils.http import urlencode
from permissions.models import Permission, Role from permissions.models import Permission
from common.utils import generate_choices_w_labels, encapsulate from common.utils import encapsulate
from common.widgets import two_state_template from common.widgets import two_state_template
from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL, from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL,
ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL) ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL)
from .models import AccessEntry, DefaultAccessEntry from .models import AccessEntry, DefaultAccessEntry
from .classes import (AccessHolder, AccessObject, AccessObjectClass, from .classes import (AccessHolder, AccessObject, AccessObjectClass,
ClassAccessHolder) ClassAccessHolder)
from .widgets import object_w_content_type_icon from .widgets import object_w_content_type_icon
from .forms import HolderSelectionForm from .forms import HolderSelectionForm
from .api import get_class_permissions_for, get_classes from .api import get_class_permissions_for
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def _permission_titles(permission_list): def _permission_titles(permission_list):
return u', '.join([unicode(permission) for permission in permission_list]) return u', '.join([unicode(permission) for permission in permission_list])
def acl_list_for(request, obj, extra_context=None): def acl_list_for(request, obj, extra_context=None):
try: try:
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL]) Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL])
@@ -46,7 +42,6 @@ def acl_list_for(request, obj, extra_context=None):
logger.debug('obj: %s' % obj) logger.debug('obj: %s' % obj)
ct = ContentType.objects.get_for_model(obj)
context = { context = {
'object_list': AccessEntry.objects.get_holders_for(obj), 'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _(u'access control lists for: %s' % obj), 'title': _(u'access control lists for: %s' % obj),
@@ -60,14 +55,14 @@ def acl_list_for(request, obj, extra_context=None):
'navigation_object_list': [ 'navigation_object_list': [
{'object': 'object'}, {'object': 'object'},
{'object': 'access_object'} {'object': 'access_object'}
], ],
} }
if extra_context: if extra_context:
context.update(extra_context) context.update(extra_context)
return render_to_response('generic_list.html', context, return render_to_response('generic_list.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def acl_list(request, app_label, model_name, object_id): def acl_list(request, app_label, model_name, object_id):
@@ -90,10 +85,10 @@ def acl_detail_for(request, actor, obj):
try: try:
Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL]) Permission.objects.check_permissions(request.user, [ACLS_VIEW_ACL])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_accesses([ACLS_VIEW_ACL], actor, obj) AccessEntry.objects.check_accesses([ACLS_VIEW_ACL], actor, obj)
permission_list = get_class_permissions_for(obj) permission_list = get_class_permissions_for(obj)
#TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware) #TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
subtemplates_list = [ subtemplates_list = [
{ {
@@ -139,7 +134,7 @@ def acl_detail_for(request, actor, obj):
context, context,
context_instance=RequestContext(request) context_instance=RequestContext(request)
) )
def acl_grant(request): def acl_grant(request):
items_property_list = loads(request.GET.get('items_property_list', [])) items_property_list = loads(request.GET.get('items_property_list', []))
@@ -152,13 +147,13 @@ def acl_grant(request):
title_suffix = [] title_suffix = []
navigation_object = None navigation_object = None
navigation_object_count = 0 navigation_object_count = 0
for item_properties in items_property_list: for item_properties in items_property_list:
try: try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']}) permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
try: try:
requester = AccessHolder.get(gid=item_properties['holder_gid']) requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid']) access_object = AccessObject.get(gid=item_properties['object_gid'])
@@ -184,13 +179,13 @@ def acl_grant(request):
items[requester][access_object].append(permission) items[requester][access_object].append(permission)
navigation_object = access_object navigation_object = access_object
navigation_object_count += 1 navigation_object_count += 1
for requester, obj_ps in items.items(): for requester, obj_ps in items.items():
for obj, ps in obj_ps.items(): for obj, ps in obj_ps.items():
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps])) title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj) title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' to %s') % requester) title_suffix.append(_(u' to %s') % requester)
if len(items_property_list) == 1: if len(items_property_list) == 1:
title_prefix = _(u'Are you sure you wish to grant the permission %(title_suffix)s?') title_prefix = _(u'Are you sure you wish to grant the permission %(title_suffix)s?')
else: else:
@@ -200,7 +195,7 @@ def acl_grant(request):
for requester, object_permissions in items.items(): for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items(): for obj, permissions in object_permissions.items():
for permission in permissions: for permission in permissions:
if AccessEntry.objects.grant(permission, requester.source_object, obj.source_object): if AccessEntry.objects.grant(permission, requester.source_object, obj.source_object):
messages.success(request, _(u'Permission "%(permission)s" granted to %(actor)s for %(object)s.') % { messages.success(request, _(u'Permission "%(permission)s" granted to %(actor)s for %(object)s.') % {
'permission': permission, 'permission': permission,
'actor': requester, 'actor': requester,
@@ -225,7 +220,7 @@ def acl_grant(request):
context['title'] = title_prefix % { context['title'] = title_prefix % {
'title_suffix': u''.join(title_suffix), 'title_suffix': u''.join(title_suffix),
} }
logger.debug('navigation_object_count: %d' % navigation_object_count) logger.debug('navigation_object_count: %d' % navigation_object_count)
logger.debug('navigation_object: %s' % navigation_object) logger.debug('navigation_object: %s' % navigation_object)
if navigation_object_count == 1: if navigation_object_count == 1:
@@ -251,21 +246,21 @@ def acl_revoke(request):
try: try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']}) permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
try: try:
requester = AccessHolder.get(gid=item_properties['holder_gid']) requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object = AccessObject.get(gid=item_properties['object_gid']) access_object = AccessObject.get(gid=item_properties['object_gid'])
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
try: try:
Permission.objects.check_permissions(request.user, [ACLS_EDIT_ACL]) Permission.objects.check_permissions(request.user, [ACLS_EDIT_ACL])
except PermissionDenied: except PermissionDenied:
try: try:
AccessEntry.objects.check_access(ACLS_EDIT_ACL, request.user, access_object) AccessEntry.objects.check_access(ACLS_EDIT_ACL, request.user, access_object)
except PermissionDenied: except PermissionDenied:
raise raise
else: else:
items.setdefault(requester, {}) items.setdefault(requester, {})
items[requester].setdefault(access_object, []) items[requester].setdefault(access_object, [])
@@ -277,14 +272,14 @@ def acl_revoke(request):
items[requester].setdefault(access_object, []) items[requester].setdefault(access_object, [])
items[requester][access_object].append(permission) items[requester][access_object].append(permission)
navigation_object = access_object navigation_object = access_object
navigation_object_count += 1 navigation_object_count += 1
for requester, obj_ps in items.items(): for requester, obj_ps in items.items():
for obj, ps in obj_ps.items(): for obj, ps in obj_ps.items():
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps])) title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj) title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' from %s') % requester) title_suffix.append(_(u' from %s') % requester)
if len(items_property_list) == 1: if len(items_property_list) == 1:
title_prefix = _(u'Are you sure you wish to revoke the permission %(title_suffix)s?') title_prefix = _(u'Are you sure you wish to revoke the permission %(title_suffix)s?')
else: else:
@@ -294,7 +289,7 @@ def acl_revoke(request):
for requester, object_permissions in items.items(): for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items(): for obj, permissions in object_permissions.items():
for permission in permissions: for permission in permissions:
if AccessEntry.objects.revoke(permission, requester.source_object, obj.source_object): if AccessEntry.objects.revoke(permission, requester.source_object, obj.source_object):
messages.success(request, _(u'Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % { messages.success(request, _(u'Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % {
'permission': permission, 'permission': permission,
'actor': requester, 'actor': requester,
@@ -319,7 +314,7 @@ def acl_revoke(request):
context['title'] = title_prefix % { context['title'] = title_prefix % {
'title_suffix': u''.join(title_suffix), 'title_suffix': u''.join(title_suffix),
} }
logger.debug('navigation_object_count: %d' % navigation_object_count) logger.debug('navigation_object_count: %d' % navigation_object_count)
logger.debug('navigation_object: %s' % navigation_object) logger.debug('navigation_object: %s' % navigation_object)
if navigation_object_count == 1: if navigation_object_count == 1:
@@ -349,7 +344,7 @@ def acl_new_holder_for(request, obj, extra_context=None, navigation_object=None)
reverse('acl_detail', args=[access_object.gid, access_holder.gid]), reverse('acl_detail', args=[access_object.gid, access_holder.gid]),
urlencode(query_string) urlencode(query_string)
) )
) )
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
else: else:
@@ -365,12 +360,12 @@ def acl_new_holder_for(request, obj, extra_context=None, navigation_object=None)
'navigation_object_list': [ 'navigation_object_list': [
{'object': 'object'}, {'object': 'object'},
{'object': 'access_object'}, {'object': 'access_object'},
], ],
} }
if extra_context: if extra_context:
context.update(extra_context) context.update(extra_context)
return render_to_response('generic_form.html', context, return render_to_response('generic_form.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
@@ -381,7 +376,7 @@ def acl_holder_new(request, access_object_gid):
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
return acl_new_holder_for(request, access_object.source_object)#, extra_context={'access_object': access_object}) return acl_new_holder_for(request, access_object.source_object) # , extra_context={'access_object': access_object})
# Setup views # Setup views
@@ -399,12 +394,12 @@ def acl_setup_valid_classes(request):
} }
return render_to_response('generic_list.html', context, return render_to_response('generic_list.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def acl_class_acl_list(request, access_object_class_gid): def acl_class_acl_list(request, access_object_class_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL]) Permission.objects.check_permissions(request.user, [ACLS_CLASS_VIEW_ACL])
access_object_class = AccessObjectClass.get(gid=access_object_class_gid) access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
context = { context = {
'object_list': DefaultAccessEntry.objects.get_holders_for(access_object_class.source_object), 'object_list': DefaultAccessEntry.objects.get_holders_for(access_object_class.source_object),
@@ -419,7 +414,7 @@ def acl_class_acl_list(request, access_object_class_gid):
} }
return render_to_response('generic_list.html', context, return render_to_response('generic_list.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid): def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid):
@@ -429,7 +424,7 @@ def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid):
access_object_class = AccessObjectClass.get(gid=access_object_class_gid) access_object_class = AccessObjectClass.get(gid=access_object_class_gid)
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
#permission_list = list(access_object_class.get_class_permissions()) #permission_list = list(access_object_class.get_class_permissions())
permission_list = get_class_permissions_for(access_object_class.content_type.model_class()) permission_list = get_class_permissions_for(access_object_class.content_type.model_class())
#TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware) #TODO : get all globally assigned permission, new function get_permissions_for_holder (roles aware)
@@ -464,9 +459,9 @@ def acl_class_acl_detail(request, access_object_class_gid, holder_object_gid):
'permission_pk': lambda x: x.pk, 'permission_pk': lambda x: x.pk,
'holder_gid': lambda x: actor.gid, 'holder_gid': lambda x: actor.gid,
'access_object_class_gid': lambda x: access_object_class.gid, 'access_object_class_gid': lambda x: access_object_class.gid,
}, },
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def acl_class_new_holder_for(request, access_object_class_gid): def acl_class_new_holder_for(request, access_object_class_gid):
Permission.objects.check_permissions(request.user, [ACLS_CLASS_EDIT_ACL]) Permission.objects.check_permissions(request.user, [ACLS_CLASS_EDIT_ACL])
@@ -489,11 +484,11 @@ def acl_class_new_holder_for(request, access_object_class_gid):
'title': _(u'add new holder for class: %s') % unicode(access_object_class), 'title': _(u'add new holder for class: %s') % unicode(access_object_class),
'object': access_object_class, 'object': access_object_class,
'submit_label': _(u'Select'), 'submit_label': _(u'Select'),
'submit_icon_famfam': 'tick' 'submit_icon_famfam': 'tick'
} }
return render_to_response('generic_form.html', context, return render_to_response('generic_form.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def acl_class_multiple_grant(request): def acl_class_multiple_grant(request):
@@ -513,25 +508,25 @@ def acl_class_multiple_grant(request):
try: try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']}) permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
try: try:
requester = AccessHolder.get(gid=item_properties['holder_gid']) requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid']) access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid'])
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
items.setdefault(requester, {}) items.setdefault(requester, {})
items[requester].setdefault(access_object_class, []) items[requester].setdefault(access_object_class, [])
items[requester][access_object_class].append(permission) items[requester][access_object_class].append(permission)
navigation_object = access_object_class navigation_object = access_object_class
navigation_object_count += 1 navigation_object_count += 1
for requester, obj_ps in items.items(): for requester, obj_ps in items.items():
for obj, ps in obj_ps.items(): for obj, ps in obj_ps.items():
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps])) title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj) title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' to %s') % requester) title_suffix.append(_(u' to %s') % requester)
if len(items_property_list) == 1: if len(items_property_list) == 1:
title_prefix = _(u'Are you sure you wish to grant the permission %(title_suffix)s?') title_prefix = _(u'Are you sure you wish to grant the permission %(title_suffix)s?')
else: else:
@@ -566,7 +561,7 @@ def acl_class_multiple_grant(request):
context['title'] = title_prefix % { context['title'] = title_prefix % {
'title_suffix': u''.join(title_suffix), 'title_suffix': u''.join(title_suffix),
} }
logger.debug('navigation_object_count: %d' % navigation_object_count) logger.debug('navigation_object_count: %d' % navigation_object_count)
logger.debug('navigation_object: %s' % navigation_object) logger.debug('navigation_object: %s' % navigation_object)
if navigation_object_count == 1: if navigation_object_count == 1:
@@ -593,25 +588,25 @@ def acl_class_multiple_revoke(request):
try: try:
permission = Permission.objects.get({'pk': item_properties['permission_pk']}) permission = Permission.objects.get({'pk': item_properties['permission_pk']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
try: try:
requester = AccessHolder.get(gid=item_properties['holder_gid']) requester = AccessHolder.get(gid=item_properties['holder_gid'])
access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid']) access_object_class = AccessObjectClass.get(gid=item_properties['access_object_class_gid'])
except ObjectDoesNotExist: except ObjectDoesNotExist:
raise Http404 raise Http404
items.setdefault(requester, {}) items.setdefault(requester, {})
items[requester].setdefault(access_object_class, []) items[requester].setdefault(access_object_class, [])
items[requester][access_object_class].append(permission) items[requester][access_object_class].append(permission)
navigation_object = access_object_class navigation_object = access_object_class
navigation_object_count += 1 navigation_object_count += 1
for requester, obj_ps in items.items(): for requester, obj_ps in items.items():
for obj, ps in obj_ps.items(): for obj, ps in obj_ps.items():
title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps])) title_suffix.append(_(u', ').join([u'"%s"' % unicode(p) for p in ps]))
title_suffix.append(_(u' for %s') % obj) title_suffix.append(_(u' for %s') % obj)
title_suffix.append(_(u' from %s') % requester) title_suffix.append(_(u' from %s') % requester)
if len(items_property_list) == 1: if len(items_property_list) == 1:
title_prefix = _(u'Are you sure you wish to revoke the permission %(title_suffix)s?') title_prefix = _(u'Are you sure you wish to revoke the permission %(title_suffix)s?')
else: else:
@@ -621,7 +616,7 @@ def acl_class_multiple_revoke(request):
for requester, object_permissions in items.items(): for requester, object_permissions in items.items():
for obj, permissions in object_permissions.items(): for obj, permissions in object_permissions.items():
for permission in permissions: for permission in permissions:
if DefaultAccessEntry.objects.revoke(permission, requester.source_object, obj.source_object): if DefaultAccessEntry.objects.revoke(permission, requester.source_object, obj.source_object):
messages.success(request, _(u'Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % { messages.success(request, _(u'Permission "%(permission)s" revoked of %(actor)s for %(object)s.') % {
'permission': permission, 'permission': permission,
'actor': requester, 'actor': requester,
@@ -646,7 +641,7 @@ def acl_class_multiple_revoke(request):
context['title'] = title_prefix % { context['title'] = title_prefix % {
'title_suffix': u''.join(title_suffix), 'title_suffix': u''.join(title_suffix),
} }
logger.debug('navigation_object_count: %d' % navigation_object_count) logger.debug('navigation_object_count: %d' % navigation_object_count)
logger.debug('navigation_object: %s' % navigation_object) logger.debug('navigation_object: %s' % navigation_object)
if navigation_object_count == 1: if navigation_object_count == 1:
+1 -6
View File
@@ -1,11 +1,6 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django import forms
from django.forms.util import flatatt
from django.utils.html import conditional_escape
from django.utils.encoding import force_unicode
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase from django.db.models.base import ModelBase
from django.template.defaultfilters import capfirst from django.template.defaultfilters import capfirst
@@ -28,5 +23,5 @@ def object_w_content_type_icon(obj):
label = obj.get_full_name() label = obj.get_full_name()
else: else:
label = unicode(obj) label = unicode(obj)
return mark_safe('%s<span>%s</span>' % (content_type_icon(content_type), capfirst(label))) return mark_safe('%s<span>%s</span>' % (content_type_icon(content_type), capfirst(label)))
-1
View File
@@ -5,7 +5,6 @@ import tempfile
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import models as auth_models from django.contrib.auth import models as auth_models
from django.contrib.auth.management import create_superuser from django.contrib.auth.management import create_superuser
from django.db.models import signals
from django.dispatch import receiver from django.dispatch import receiver
from django.db.models.signals import post_syncdb from django.db.models.signals import post_syncdb
+10 -10
View File
@@ -1,4 +1,4 @@
import os, tempfile, zipfile import zipfile
try: try:
import zlib import zlib
@@ -24,11 +24,11 @@ class CompressedFile(object):
self._open(file_input) self._open(file_input)
else: else:
self._create() self._create()
def _create(self): def _create(self):
self.descriptor = StringIO() self.descriptor = StringIO()
self.zf = zipfile.ZipFile(self.descriptor, mode='w') self.zf = zipfile.ZipFile(self.descriptor, mode='w')
def _open(self, file_input): def _open(self, file_input):
try: try:
# Is it a file like object? # Is it a file like object?
@@ -37,7 +37,7 @@ class CompressedFile(object):
# If not, try open it. # If not, try open it.
self.descriptor = open(file_input, 'r+b') self.descriptor = open(file_input, 'r+b')
else: else:
self.descriptor = file_input self.descriptor = file_input
try: try:
test = zipfile.ZipFile(self.descriptor, mode='r') test = zipfile.ZipFile(self.descriptor, mode='r')
@@ -54,23 +54,23 @@ class CompressedFile(object):
file_input.seek(0) file_input.seek(0)
except AttributeError: except AttributeError:
# If not, keep it # If not, keep it
self.zf.write(filename, arcname=arcname, compress_type=COMPRESSION) self.zf.write(file_input, arcname=arcname, compress_type=COMPRESSION)
else: else:
self.zf.writestr(arcname, file_input.read()) self.zf.writestr(arcname, file_input.read())
def contents(self): def contents(self):
return [filename for filename in self.zf.namelist() if not filename.endswith('/')] return [filename for filename in self.zf.namelist() if not filename.endswith('/')]
def get_content(self, filename): def get_content(self, filename):
return self.zf.read(filename) return self.zf.read(filename)
def write(self, filename=None): def write(self, filename=None):
# fix for Linux zip files read in Windows # fix for Linux zip files read in Windows
for file in self.zf.filelist: for file in self.zf.filelist:
file.create_system = 0 file.create_system = 0
self.descriptor.seek(0) self.descriptor.seek(0)
if filename: if filename:
descriptor = open(filename, 'w') descriptor = open(filename, 'w')
descriptor.write(self.descriptor.read()) descriptor.write(self.descriptor.read())
+9 -9
View File
@@ -92,10 +92,10 @@ class FilterForm(forms.Form):
class ChoiceForm(forms.Form): class ChoiceForm(forms.Form):
''' """
Form to be used in side by side templates used to add or remove Form to be used in side by side templates used to add or remove
items from a many to many field items from a many to many field
''' """
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
choices = kwargs.pop('choices', []) choices = kwargs.pop('choices', [])
label = kwargs.pop('label', _(u'Selection')) label = kwargs.pop('label', _(u'Selection'))
@@ -108,28 +108,28 @@ class ChoiceForm(forms.Form):
class UserForm_view(DetailForm): class UserForm_view(DetailForm):
''' """
Form used to display an user's public details Form used to display an user's public details
''' """
class Meta: class Meta:
model = User model = User
fields = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'is_superuser', 'last_login', 'date_joined', 'groups') fields = ('username', 'first_name', 'last_name', 'email', 'is_staff', 'is_superuser', 'last_login', 'date_joined', 'groups')
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
''' """
Form used to edit an user's mininal fields by the user himself Form used to edit an user's mininal fields by the user himself
''' """
class Meta: class Meta:
model = User model = User
fields = ('first_name', 'last_name') fields = ('first_name', 'last_name')
class EmailAuthenticationForm(AuthenticationForm): class EmailAuthenticationForm(AuthenticationForm):
''' """
Override the default authentication form to use email address Override the default authentication form to use email address
authentication authentication
''' """
email = forms.CharField(label=_(u'Email'), max_length=75, email = forms.CharField(label=_(u'Email'), max_length=75,
widget=EmailInput() widget=EmailInput()
) )
@@ -153,7 +153,7 @@ EmailAuthenticationForm.base_fields.keyOrder = ['email', 'password']
class FileDisplayForm(forms.Form): class FileDisplayForm(forms.Form):
text = forms.CharField( text = forms.CharField(
label='',#_(u'Text'), label='', # _(u'Text'),
widget=forms.widgets.Textarea( widget=forms.widgets.Textarea(
attrs={'cols': 40, 'rows': 20, 'readonly': 'readonly'} attrs={'cols': 40, 'rows': 20, 'readonly': 'readonly'}
) )
+2 -2
View File
@@ -34,14 +34,14 @@ class AnonymousUserSingletonManager(SingletonManager):
return self.model.objects.get() return self.model.objects.get()
else: else:
return user return user
class AnonymousUserSingleton(Singleton): class AnonymousUserSingleton(Singleton):
objects = AnonymousUserSingletonManager() objects = AnonymousUserSingletonManager()
def __unicode__(self): def __unicode__(self):
return ugettext('Anonymous user') return ugettext('Anonymous user')
class Meta: class Meta:
verbose_name = _(u'anonymous user') verbose_name = _(u'anonymous user')
verbose_name_plural = _(u'anonymous user') verbose_name_plural = _(u'anonymous user')
+7 -5
View File
@@ -1,12 +1,13 @@
from django import template from django import template
register = template.Library() register = template.Library()
class SetVarNode(template.Node): class SetVarNode(template.Node):
def __init__(self, var_name, var_value): def __init__(self, var_name, var_value):
self.var_name = var_name self.var_name = var_name
self.var_value = var_value self.var_value = var_value
def render(self, context): def render(self, context):
try: try:
value = template.Variable(self.var_value).resolve(context) value = template.Variable(self.var_value).resolve(context)
@@ -17,7 +18,8 @@ class SetVarNode(template.Node):
context.dicts[0][self.var_name] = value context.dicts[0][self.var_name] = value
return u"" return u""
def set_var(parser, token): def set_var(parser, token):
""" """
{% set <var_name> = <var_value> %} {% set <var_name> = <var_value> %}
@@ -26,5 +28,5 @@ def set_var(parser, token):
if len(parts) < 4: if len(parts) < 4:
raise template.TemplateSyntaxError("'set' tag must be of the form: {% set <var_name> = <var_value> %}") raise template.TemplateSyntaxError("'set' tag must be of the form: {% set <var_name> = <var_value> %}")
return SetVarNode(parts[1], parts[3]) return SetVarNode(parts[1], parts[3])
register.tag('set', set_var) register.tag('set', set_var)
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+7 -7
View File
@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import from __future__ import absolute_import
import os import os
@@ -18,7 +18,7 @@ from django.contrib.auth.models import User
def urlquote(link=None, get=None): def urlquote(link=None, get=None):
u''' u"""
This method does both: urlquote() and urlencode() This method does both: urlquote() and urlencode()
urlqoute(): Quote special characters in 'link' urlqoute(): Quote special characters in 'link'
@@ -33,7 +33,7 @@ def urlquote(link=None, get=None):
urlquote('/mypath/', {'key': 'value'}) --> '/mypath/?key=value' urlquote('/mypath/', {'key': 'value'}) --> '/mypath/?key=value'
urlquote('/mypath/', {'key': ['value1', 'value2']}) --> '/mypath/?key=value1&key=value2' urlquote('/mypath/', {'key': ['value1', 'value2']}) --> '/mypath/?key=value1&key=value2'
urlquote({'key': ['value1', 'value2']}) --> 'key=value1&key=value2' urlquote({'key': ['value1', 'value2']}) --> 'key=value1&key=value2'
''' """
if get is None: if get is None:
get = [] get = []
@@ -112,9 +112,9 @@ def pretty_size_10(size):
# http://www.johncardinal.com/tmgutil/capitalizenames.htm # http://www.johncardinal.com/tmgutil/capitalizenames.htm
def proper_name(name): def proper_name(name):
''' """
Does the work of capitalizing a name (can be a full name). Does the work of capitalizing a name (can be a full name).
''' """
mc = re.compile(r'^Mc(\w)(?=\w)', re.I) mc = re.compile(r'^Mc(\w)(?=\w)', re.I)
mac = re.compile(r'^Mac(\w)(?=\w)', re.I) mac = re.compile(r'^Mac(\w)(?=\w)', re.I)
suffixes = [ suffixes = [
@@ -330,7 +330,7 @@ def generate_choices_w_labels(choices, display_object_type=True):
return sorted(results, key=lambda x: x[1]) return sorted(results, key=lambda x: x[1])
def get_object_name(obj, display_object_type=True): def get_object_name(obj, display_object_type=True):
ct_label = ContentType.objects.get_for_model(obj).name ct_label = ContentType.objects.get_for_model(obj).name
if isinstance(obj, User): if isinstance(obj, User):
label = obj.get_full_name() if obj.get_full_name() else obj label = obj.get_full_name() if obj.get_full_name() else obj
@@ -342,7 +342,7 @@ def get_object_name(obj, display_object_type=True):
verbose_name = unicode(obj._meta.verbose_name) verbose_name = unicode(obj._meta.verbose_name)
except AttributeError: except AttributeError:
verbose_name = ct_label verbose_name = ct_label
return u'%s: %s' % (verbose_name, label) return u'%s: %s' % (verbose_name, label)
else: else:
return u'%s' % (label) return u'%s' % (label)
+19 -19
View File
@@ -18,19 +18,19 @@ from .conf.settings import LOGIN_METHOD
def password_change_done(request): def password_change_done(request):
''' """
View called when the new user password has been accepted View called when the new user password has been accepted
''' """
messages.success(request, _(u'Your password has been successfully changed.')) messages.success(request, _(u'Your password has been successfully changed.'))
return redirect('home') return redirect('home')
def multi_object_action_view(request): def multi_object_action_view(request):
''' """
Proxy view called first when using a multi object action, which Proxy view called first when using a multi object action, which
then redirects to the appropiate specialized view then redirects to the appropiate specialized view
''' """
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
@@ -83,7 +83,7 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
flat_list.extend(group[1]) flat_list.extend(group[1])
else: else:
flat_list = left_list() flat_list = left_list()
label = dict(flat_list)[selection] label = dict(flat_list)[selection]
if decode_content_type: if decode_content_type:
selection_obj = get_obj_from_content_type_string(selection) selection_obj = get_obj_from_content_type_string(selection)
@@ -109,7 +109,7 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
flat_list.extend(group[1]) flat_list.extend(group[1])
else: else:
flat_list = right_list() flat_list = right_list()
label = dict(flat_list)[selection] label = dict(flat_list)[selection]
if decode_content_type: if decode_content_type:
selection = get_obj_from_content_type_string(selection) selection = get_obj_from_content_type_string(selection)
@@ -159,9 +159,9 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
def current_user_details(request): def current_user_details(request):
''' """
Display the current user's details Display the current user's details
''' """
form = UserForm_view(instance=request.user) form = UserForm_view(instance=request.user)
return render_to_response( return render_to_response(
@@ -174,9 +174,9 @@ def current_user_details(request):
def current_user_edit(request): def current_user_edit(request):
''' """
Allow an user to edit his own details Allow an user to edit his own details
''' """
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('current_user_details')))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', reverse('current_user_details'))))
@@ -199,15 +199,15 @@ def current_user_edit(request):
def login_view(request): def login_view(request):
''' """
Control how the use is to be authenticated, options are 'email' and Control how the use is to be authenticated, options are 'email' and
'username' 'username'
''' """
kwargs = {'template_name': 'login.html'} kwargs = {'template_name': 'login.html'}
if LOGIN_METHOD == 'email': if LOGIN_METHOD == 'email':
kwargs['authentication_form'] = EmailAuthenticationForm kwargs['authentication_form'] = EmailAuthenticationForm
if not request.user.is_authenticated(): if not request.user.is_authenticated():
context = {'web_theme_view_type': 'plain'} context = {'web_theme_view_type': 'plain'}
else: else:
@@ -217,9 +217,9 @@ def login_view(request):
def changelog_view(request): def changelog_view(request):
''' """
Display the included Changelog.txt file from the about menu Display the included Changelog.txt file from the about menu
''' """
form = ChangelogForm() form = ChangelogForm()
return render_to_response( return render_to_response(
'generic_detail.html', { 'generic_detail.html', {
@@ -230,9 +230,9 @@ def changelog_view(request):
def license_view(request): def license_view(request):
''' """
Display the included LICENSE file from the about menu Display the included LICENSE file from the about menu
''' """
form = LicenseForm() form = LicenseForm()
return render_to_response( return render_to_response(
'generic_detail.html', { 'generic_detail.html', {
+13 -12
View File
@@ -10,10 +10,10 @@ from django.utils.encoding import force_unicode
class PlainWidget(forms.widgets.Widget): class PlainWidget(forms.widgets.Widget):
''' """
Class to define a form widget that effectively nulls the htmls of a Class to define a form widget that effectively nulls the htmls of a
widget and reduces the output to only it's value widget and reduces the output to only it's value
''' """
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
return mark_safe(u'%s' % value) return mark_safe(u'%s' % value)
@@ -74,11 +74,11 @@ def two_state_template(state, famfam_ok_icon=u'tick', famfam_fail_icon=u'cross')
class TextAreaDiv(forms.widgets.Widget): class TextAreaDiv(forms.widgets.Widget):
''' """
Class to define a form widget that simulates the behavior of a Class to define a form widget that simulates the behavior of a
Textarea widget but using a div tag instead Textarea widget but using a div tag instead
''' """
def __init__(self, attrs=None): def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness. # The 'rows' and 'cols' attributes are required for HTML correctness.
default_attrs = {'class': 'text_area_div'} default_attrs = {'class': 'text_area_div'}
@@ -98,10 +98,10 @@ class TextAreaDiv(forms.widgets.Widget):
# From: http://www.peterbe.com/plog/emailinput-html5-django # From: http://www.peterbe.com/plog/emailinput-html5-django
class EmailInput(forms.widgets.Input): class EmailInput(forms.widgets.Input):
''' """
Class for a login form widget that accepts only well formated Class for a login form widget that accepts only well formated
email address email address
''' """
input_type = 'email' input_type = 'email'
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
@@ -114,13 +114,14 @@ class EmailInput(forms.widgets.Input):
class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple): class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
''' """
Class for a form widget composed of a selection of checkboxes wrapped Class for a form widget composed of a selection of checkboxes wrapped
in a div tag with automatic overflow to add scrollbars when the list in a div tag with automatic overflow to add scrollbars when the list
exceds the height of the div exceds the height of the div
''' """
def render(self, name, value, attrs=None, choices=()): def render(self, name, value, attrs=None, choices=()):
if value is None: value = [] if value is None:
value = []
has_id = attrs and 'id' in attrs has_id = attrs and 'id' in attrs
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs(attrs, name=name)
output = [u'<ul class="undecorated_list" style="margin-left: 5px; margin-top: 3px; margin-bottom: 3px;">'] output = [u'<ul class="undecorated_list" style="margin-left: 5px; margin-top: 3px; margin-bottom: 3px;">']
@@ -141,5 +142,5 @@ class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
option_label = conditional_escape(force_unicode(option_label)) option_label = conditional_escape(force_unicode(option_label))
output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label)) output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label))
output.append(u'</ul>') output.append(u'</ul>')
return mark_safe(u'<div class="text_area_div">%s</div>' % u'\n'.join(output)) return mark_safe(u'<div class="text_area_div">%s</div>' % u'\n'.join(output))
+9 -9
View File
@@ -1,4 +1,4 @@
'''Common abstract classes for forms.''' """Common abstract classes for forms."""
try: try:
import cPickle as pickle import cPickle as pickle
except ImportError: except ImportError:
@@ -15,13 +15,13 @@ __all__ = ('security_hash', 'BoundFormWizard')
def security_hash_new(form, exclude=None, *args): def security_hash_new(form, exclude=None, *args):
''' """
Calculates a security hash for the given Form/FormSet instance. Calculates a security hash for the given Form/FormSet instance.
This creates a list of the form field names/values in a deterministic This creates a list of the form field names/values in a deterministic
order, pickles the result with the SECRET_KEY setting, then takes an md5 order, pickles the result with the SECRET_KEY setting, then takes an md5
hash of that. hash of that.
''' """
data = [] data = []
if exclude is None: if exclude is None:
@@ -52,20 +52,20 @@ def security_hash_new(form, exclude=None, *args):
class BoundFormWizard(FormWizard): class BoundFormWizard(FormWizard):
''' """
Render prev_fields as a list of bound form fields in the template Render prev_fields as a list of bound form fields in the template
context rather than raw html. context rather than raw html.
''' """
def security_hash(self, request, form): def security_hash(self, request, form):
''' """
Calculates the security hash for the given HttpRequest and Calculates the security hash for the given HttpRequest and
Form/FormSet instances. Form/FormSet instances.
Subclasses may want to take into account request-specific information, Subclasses may want to take into account request-specific information,
such as the IP address. such as the IP address.
''' """
return security_hash_new(form) return security_hash_new(form)
def render(self, form, request, step, context=None): def render(self, form, request, step, context=None):
+9 -10
View File
@@ -15,11 +15,11 @@ from .literals import (TRANSFORMATION_CHOICES, TRANSFORMATION_RESIZE,
FILE_FORMATS) FILE_FORMATS)
from .utils import cleanup from .utils import cleanup
from .runtime import office_converter from .runtime import office_converter
from .exceptions import OfficeConversionError from .exceptions import OfficeConversionError, UnknownFileFormat
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest() HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
def cache_cleanup(input_filepath, *args, **kwargs): def cache_cleanup(input_filepath, *args, **kwargs):
try: try:
os.remove(create_image_cache_filename(input_filepath, *args, **kwargs)) os.remove(create_image_cache_filename(input_filepath, *args, **kwargs))
@@ -42,13 +42,13 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
rotation = kwargs.get('rotation', DEFAULT_ROTATION) rotation = kwargs.get('rotation', DEFAULT_ROTATION)
page = kwargs.get('page', DEFAULT_PAGE_NUMBER) page = kwargs.get('page', DEFAULT_PAGE_NUMBER)
transformations = kwargs.get('transformations', []) transformations = kwargs.get('transformations', [])
if transformations is None: if transformations is None:
transformations = [] transformations = []
if output_filepath is None: if output_filepath is None:
output_filepath = create_image_cache_filename(input_filepath, *args, **kwargs) output_filepath = create_image_cache_filename(input_filepath, *args, **kwargs)
if os.path.exists(output_filepath): if os.path.exists(output_filepath):
return output_filepath return output_filepath
@@ -79,7 +79,7 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
'transformation': TRANSFORMATION_ZOOM, 'transformation': TRANSFORMATION_ZOOM,
'arguments': {'percent': zoom} 'arguments': {'percent': zoom}
} }
) )
if rotation != 0 and rotation != 360: if rotation != 0 and rotation != 360:
transformations.append( transformations.append(
@@ -87,7 +87,7 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
'transformation': TRANSFORMATION_ROTATE, 'transformation': TRANSFORMATION_ROTATE,
'arguments': {'degrees': rotation} 'arguments': {'degrees': rotation}
} }
) )
try: try:
backend.convert_file(input_filepath=input_filepath, output_filepath=output_filepath, transformations=transformations, page=page, file_format=file_format, mimetype=mimetype) backend.convert_file(input_filepath=input_filepath, output_filepath=output_filepath, transformations=transformations, page=page, file_format=file_format, mimetype=mimetype)
@@ -107,7 +107,7 @@ def get_page_count(input_filepath):
except OfficeConversionError: except OfficeConversionError:
raise UnknownFileFormat('office converter exception') raise UnknownFileFormat('office converter exception')
return backend.get_page_count(input_filepath) return backend.get_page_count(input_filepath)
''' '''
@@ -127,8 +127,7 @@ def get_available_transformations_choices():
result.append([transformation, transformation_template]) result.append([transformation, transformation_template])
return result return result
def get_format_list(): def get_format_list():
return [(format, FILE_FORMATS.get(format, u'')) for format in backend.get_format_list()] return [(format, FILE_FORMATS.get(format, u'')) for format in backend.get_format_list()]
+8 -8
View File
@@ -1,29 +1,29 @@
class ConvertError(Exception): class ConvertError(Exception):
''' """
Base exception for all coverter app exceptions Base exception for all coverter app exceptions
''' """
pass pass
class UnknownFileFormat(ConvertError): class UnknownFileFormat(ConvertError):
''' """
Raised when the converter backend can't understand a file Raised when the converter backend can't understand a file
''' """
pass pass
class IdentifyError(ConvertError): class IdentifyError(ConvertError):
''' """
Raised by the graphcismagick and imagemagics identify program Raised by the graphcismagick and imagemagics identify program
''' """
pass pass
class UnkownConvertError(ConvertError): class UnkownConvertError(ConvertError):
''' """
Raised when an error is found but there is no disernible way to Raised when an error is found but there is no disernible way to
identify the kind of error identify the kind of error
''' """
pass pass
+4 -4
View File
@@ -53,7 +53,7 @@ FILE_FORMATS = {
'8BIN': _(u'Photoshop resource format'), '8BIN': _(u'Photoshop resource format'),
'8BIMTEXT': _(u'Photoshop resource text format'), '8BIMTEXT': _(u'Photoshop resource text format'),
'8BIMWTEXT': _(u'Photoshop resource wide text format'), '8BIMWTEXT': _(u'Photoshop resource wide text format'),
'A': _(u'Raw alpha samples'), 'A': _(u'Raw alpha samples'),
'AI': _(u'Adobe Illustrator CS2'), 'AI': _(u'Adobe Illustrator CS2'),
'APP1': _(u'Raw application information'), 'APP1': _(u'Raw application information'),
@@ -62,7 +62,7 @@ FILE_FORMATS = {
'ARW': _(u'Sony Alpha DSLR Raw Image Format'), 'ARW': _(u'Sony Alpha DSLR Raw Image Format'),
'AVI': _(u'Microsoft Audio/Visual Interleaved'), 'AVI': _(u'Microsoft Audio/Visual Interleaved'),
'AVS': _(u'AVS X image'), 'AVS': _(u'AVS X image'),
'B': _(u'Raw blue samples'), 'B': _(u'Raw blue samples'),
'BGR': _(u'Raw blue, green, and red samples'), 'BGR': _(u'Raw blue, green, and red samples'),
'BGRA': _(u'Raw blue, green, red and alpha samples'), 'BGRA': _(u'Raw blue, green, red and alpha samples'),
@@ -95,7 +95,7 @@ FILE_FORMATS = {
'DJVU': _(u'Déjà vu'), 'DJVU': _(u'Déjà vu'),
'DNG': _(u'Adobe Digital Negative'), 'DNG': _(u'Adobe Digital Negative'),
'DOT': _(u'Graphviz'), 'DOT': _(u'Graphviz'),
'DPX': _(u'SMPTE 268M-2003 (DPX 2.0)'), 'DPX': _(u'SMPTE 268M-2003 (DPX 2.0)'),
'EPDF': _(u'Encapsulated Portable Document Format'), 'EPDF': _(u'Encapsulated Portable Document Format'),
'EPI': _(u'Adobe Encapsulated PostScript Interchange format'), 'EPI': _(u'Adobe Encapsulated PostScript Interchange format'),
@@ -110,7 +110,7 @@ FILE_FORMATS = {
'ERF': _(u'Epson RAW Format'), 'ERF': _(u'Epson RAW Format'),
'EXIF': _(u'Exif digital camera binary data'), 'EXIF': _(u'Exif digital camera binary data'),
'EXR': _(u'High Dynamic-range (HDR)'), 'EXR': _(u'High Dynamic-range (HDR)'),
'FAX': _(u'Group 3 FAX (Not TIFF Group3 FAX)'), 'FAX': _(u'Group 3 FAX (Not TIFF Group3 FAX)'),
'FLI': _(u'Autodesk FLI animations file'), 'FLI': _(u'Autodesk FLI animations file'),
'FLC': _(u'Autodesk FLC animations file'), 'FLC': _(u'Autodesk FLC animations file'),
+8 -8
View File
@@ -13,14 +13,14 @@ from .exceptions import (OfficeConversionError,
OfficeBackendError, UnknownFileFormat) OfficeBackendError, UnknownFileFormat)
CACHED_FILE_SUFFIX = u'_office_converter' CACHED_FILE_SUFFIX = u'_office_converter'
CONVERTER_OFFICE_FILE_MIMETYPES = [ CONVERTER_OFFICE_FILE_MIMETYPES = [
u'application/msword', u'application/msword',
u'application/mswrite', u'application/mswrite',
u'application/mspowerpoint', u'application/mspowerpoint',
u'application/msexcel', u'application/msexcel',
u'application/vnd.ms-excel', u'application/vnd.ms-excel',
u'application/vnd.ms-powerpoint', u'application/vnd.ms-powerpoint',
u'application/vnd.oasis.opendocument.presentation', u'application/vnd.oasis.opendocument.presentation',
u'application/vnd.oasis.opendocument.text', u'application/vnd.oasis.opendocument.text',
u'application/vnd.openxmlformats-officedocument.wordprocessingml.document', u'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
@@ -43,7 +43,7 @@ class OfficeConverter(object):
self.exists = False self.exists = False
self.mimetype = None self.mimetype = None
self.encoding = None self.encoding = None
def mimetypes(self): def mimetypes(self):
return CONVERTER_OFFICE_FILE_MIMETYPES return CONVERTER_OFFICE_FILE_MIMETYPES
@@ -51,7 +51,7 @@ class OfficeConverter(object):
self.exists = False self.exists = False
self.mimetype = None self.mimetype = None
self.encoding = None self.encoding = None
self.input_filepath = input_filepath self.input_filepath = input_filepath
# Make sure file is of a known office format # Make sure file is of a known office format
@@ -71,13 +71,13 @@ class OfficeConverter(object):
except OfficeBackendError, msg: except OfficeBackendError, msg:
# convert exception so that at least the mime type icon is displayed # convert exception so that at least the mime type icon is displayed
raise UnknownFileFormat(msg) raise UnknownFileFormat(msg)
def __unicode__(self): def __unicode__(self):
return getattr(self, 'output_filepath', None) return getattr(self, 'output_filepath', None)
def __str__(self): def __str__(self):
return str(self.__unicode__()) return str(self.__unicode__())
class OfficeConverterBackendUnoconv(object): class OfficeConverterBackendUnoconv(object):
def __init__(self): def __init__(self):
@@ -91,7 +91,7 @@ class OfficeConverterBackendUnoconv(object):
''' '''
self.input_filepath = input_filepath self.input_filepath = input_filepath
self.output_filepath = output_filepath self.output_filepath = output_filepath
command = [] command = []
command.append(self.unoconv_path) command.append(self.unoconv_path)
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+1 -4
View File
@@ -2,10 +2,7 @@ from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from navigation.api import (register_links, register_top_menu, from navigation.api import register_links
register_model_list_columns, register_multi_item_links,
register_sidebar_template)
from main.api import register_diagnostic, register_maintenance_links
from project_setup.api import register_setup from project_setup.api import register_setup
from hkp import Key as KeyServerKey from hkp import Key as KeyServerKey
+16 -21
View File
@@ -1,15 +1,10 @@
from __future__ import absolute_import from __future__ import absolute_import
import types
from pickle import dumps
import logging import logging
import tempfile import tempfile
import os import os
from django.core.files.base import File
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.http import urlquote_plus
from hkp import KeyServer from hkp import KeyServer
import gnupg import gnupg
@@ -73,7 +68,7 @@ SIGNATURE_STATES = {
'text': _(u'Document is signed with a valid signature.'), 'text': _(u'Document is signed with a valid signature.'),
'icon': 'document_signature.png' 'icon': 'document_signature.png'
}, },
} }
class Key(object): class Key(object):
@@ -110,7 +105,7 @@ class Key(object):
keys = gpg.gpg.list_keys(secret=secret) keys = gpg.gpg.list_keys(secret=secret)
key = next((key for key in keys if key['keyid'] == key_id), None) key = next((key for key in keys if key['keyid'] == key_id), None)
if not key: if not key:
if search_keyservers and secret==False: if search_keyservers and secret == False:
try: try:
gpg.receive_key(key_id) gpg.receive_key(key_id)
return Key(gpg, key_id) return Key(gpg, key_id)
@@ -162,8 +157,8 @@ class GPG(object):
# If not, try open it. # If not, try open it.
return open(file_input, 'rb') return open(file_input, 'rb')
else: else:
return file_input return file_input
def __init__(self, binary_path=None, home=None, keyring=None, keyservers=None): def __init__(self, binary_path=None, home=None, keyring=None, keyservers=None):
kwargs = {} kwargs = {}
if binary_path: if binary_path:
@@ -203,9 +198,9 @@ class GPG(object):
''' '''
Verify the signature of a file. Verify the signature of a file.
''' '''
input_descriptor = GPG.get_descriptor(file_input) input_descriptor = GPG.get_descriptor(file_input)
if detached_signature: if detached_signature:
# Save the original data and invert the argument order # Save the original data and invert the argument order
# Signature first, file second # Signature first, file second
@@ -217,10 +212,10 @@ class GPG(object):
verify = self.gpg.verify_file(detached_signature, data_filename=filename) verify = self.gpg.verify_file(detached_signature, data_filename=filename)
else: else:
verify = self.gpg.verify_file(input_descriptor) verify = self.gpg.verify_file(input_descriptor)
if close_descriptor: if close_descriptor:
input_descriptor.close() input_descriptor.close()
if verify: if verify:
return verify return verify
#elif getattr(verify, 'status', None) == 'no public key': #elif getattr(verify, 'status', None) == 'no public key':
@@ -245,7 +240,7 @@ class GPG(object):
overrided if it already exists), if no destination file name is overrided if it already exists), if no destination file name is
provided the signature is returned. provided the signature is returned.
''' '''
kwargs = {} kwargs = {}
kwargs['clearsign'] = clearsign kwargs['clearsign'] = clearsign
@@ -292,12 +287,12 @@ class GPG(object):
result = self.gpg.decrypt_file(input_descriptor) result = self.gpg.decrypt_file(input_descriptor)
if close_descriptor: if close_descriptor:
input_descriptor.close() input_descriptor.close()
if not result.status: if not result.status:
raise GPGDecryptionError('Unable to decrypt file') raise GPGDecryptionError('Unable to decrypt file')
return result return result
def create_key(self, *args, **kwargs): def create_key(self, *args, **kwargs):
if kwargs.get('passphrase') == u'': if kwargs.get('passphrase') == u'':
kwargs.pop('passphrase') kwargs.pop('passphrase')
@@ -324,7 +319,7 @@ class GPG(object):
return Key.get(self, import_result.fingerprints[0], secret=False) return Key.get(self, import_result.fingerprints[0], secret=False)
raise KeyFetchingError raise KeyFetchingError
def query(self, term): def query(self, term):
results = {} results = {}
for keyserver in self.keyservers: for keyserver in self.keyservers:
@@ -336,14 +331,14 @@ class GPG(object):
results[key.keyid] = key results[key.keyid] = key
except: except:
pass pass
return results.values() return results.values()
def import_key(self, key_data): def import_key(self, key_data):
import_result = self.gpg.import_keys(key_data) import_result = self.gpg.import_keys(key_data)
logger.debug('import_result: %s' % import_result) logger.debug('import_result: %s' % import_result)
if import_result: if import_result:
return Key.get(self, import_result.fingerprints[0], secret=False) return Key.get(self, import_result.fingerprints[0], secret=False)
raise KeyImportError raise KeyImportError
-3
View File
@@ -1,9 +1,6 @@
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.utils.translation import ugettext
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.conf import settings
class KeySearchForm(forms.Form): class KeySearchForm(forms.Form):
-1
View File
@@ -1 +0,0 @@
+20 -26
View File
@@ -1,22 +1,16 @@
from __future__ import absolute_import from __future__ import absolute_import
from datetime import datetime
import logging import logging
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
from django.contrib import messages from django.contrib import messages
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.conf import settings
from django.template.defaultfilters import force_escape
from permissions.models import Permission from permissions.models import Permission
from common.utils import pretty_size, parse_range, urlquote, \ from common.utils import (urlquote, encapsulate)
return_diff, encapsulate
from .api import Key, SIGNATURE_STATES from .api import Key, SIGNATURE_STATES
from .runtime import gpg from .runtime import gpg
from .exceptions import (GPGVerificationError, KeyFetchingError, from .exceptions import (GPGVerificationError, KeyFetchingError,
@@ -30,7 +24,7 @@ logger = logging.getLogger(__name__)
def key_receive(request, key_id): def key_receive(request, key_id):
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_RECEIVE]) Permission.objects.check_permissions(request.user, [PERMISSION_KEY_RECEIVE])
post_action_redirect = None post_action_redirect = None
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
@@ -54,13 +48,13 @@ def key_receive(request, key_id):
'next': next, 'next': next,
'previous': previous, 'previous': previous,
'submit_method': 'GET', 'submit_method': 'GET',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def key_list(request, secret=True): def key_list(request, secret=True):
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_KEY_VIEW])
if secret: if secret:
object_list = Key.get_all(gpg, secret=True) object_list = Key.get_all(gpg, secret=True)
title = _(u'private keys') title = _(u'private keys')
@@ -87,7 +81,7 @@ def key_list(request, secret=True):
def key_delete(request, fingerprint, key_type): def key_delete(request, fingerprint, key_type):
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_DELETE]) Permission.objects.check_permissions(request.user, [PERMISSION_KEY_DELETE])
secret = key_type == 'sec' secret = key_type == 'sec'
key = Key.get(gpg, fingerprint, secret=secret) key = Key.get(gpg, fingerprint, secret=secret)
@@ -116,7 +110,7 @@ def key_delete(request, fingerprint, key_type):
def key_query(request): def key_query(request):
Permission.objects.check_permissions(request.user, [PERMISSION_KEYSERVER_QUERY]) Permission.objects.check_permissions(request.user, [PERMISSION_KEYSERVER_QUERY])
subtemplates_list = [] subtemplates_list = []
term = request.GET.get('term') term = request.GET.get('term')
@@ -130,8 +124,8 @@ def key_query(request):
'submit_method': 'GET', 'submit_method': 'GET',
}, },
} }
) )
if term: if term:
results = gpg.query(term) results = gpg.query(term)
subtemplates_list.append( subtemplates_list.append(
@@ -153,36 +147,36 @@ def key_query(request):
{ {
'name': _(u'creation date'), 'name': _(u'creation date'),
'attribute': 'creation_date', 'attribute': 'creation_date',
}, },
{ {
'name': _(u'disabled'), 'name': _(u'disabled'),
'attribute': 'disabled', 'attribute': 'disabled',
}, },
{ {
'name': _(u'expiration date'), 'name': _(u'expiration date'),
'attribute': 'expiration_date', 'attribute': 'expiration_date',
}, },
{ {
'name': _(u'expired'), 'name': _(u'expired'),
'attribute': 'expired', 'attribute': 'expired',
}, },
{ {
'name': _(u'length'), 'name': _(u'length'),
'attribute': 'key_length', 'attribute': 'key_length',
}, },
{ {
'name': _(u'revoked'), 'name': _(u'revoked'),
'attribute': 'revoked', 'attribute': 'revoked',
}, },
{ {
'name': _(u'Identifies'), 'name': _(u'Identifies'),
'attribute': encapsulate(lambda x: u', '.join([identity.uid for identity in x.identities])), 'attribute': encapsulate(lambda x: u', '.join([identity.uid for identity in x.identities])),
}, },
] ]
}, },
} }
) )
return render_to_response('generic_form.html', { return render_to_response('generic_form.html', {
'subtemplates_list': subtemplates_list, 'subtemplates_list': subtemplates_list,
+1 -2
View File
@@ -1,8 +1,7 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from documents.models import Document from documents.models import Document
from navigation.api import register_links, register_multi_item_links from navigation.api import register_links
from project_setup.api import register_setup
from acls import ACLS_VIEW_ACL, ACLS_EDIT_ACL from acls import ACLS_VIEW_ACL, ACLS_EDIT_ACL
from acls.api import class_permissions from acls.api import class_permissions
+9 -10
View File
@@ -1,17 +1,16 @@
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from documents.models import Document from documents.models import Document
from acls.views import acl_list_for from acls.views import acl_list_for
from acls.models import AccessEntry
def document_acl_list(request, document_id): def document_acl_list(request, document_id):
document = get_object_or_404(Document, pk=document_id) document = get_object_or_404(Document, pk=document_id)
return acl_list_for( return acl_list_for(
request, request,
document, document,
extra_context={ extra_context={
'object': document, 'object': document,
} }
) )
+1 -2
View File
@@ -6,7 +6,6 @@ from django.contrib.comments.models import Comment
from django.contrib.contenttypes import generic from django.contrib.contenttypes import generic
from navigation.api import register_links, register_model_list_columns from navigation.api import register_links, register_model_list_columns
from permissions.models import PermissionNamespace, Permission
from common.utils import encapsulate from common.utils import encapsulate
from acls.api import class_permissions from acls.api import class_permissions
from documents.models import Document from documents.models import Document
@@ -16,7 +15,7 @@ if 'django.contrib.comments' not in settings.INSTALLED_APPS:
from .permissions import (PERMISSION_COMMENT_CREATE, from .permissions import (PERMISSION_COMMENT_CREATE,
PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_VIEW) PERMISSION_COMMENT_DELETE, PERMISSION_COMMENT_VIEW)
comment_delete = {'text': _('delete'), 'view': 'comment_delete', 'args': 'object.pk', 'famfam': 'comment_delete', 'permissions': [PERMISSION_COMMENT_DELETE]} comment_delete = {'text': _('delete'), 'view': 'comment_delete', 'args': 'object.pk', 'famfam': 'comment_delete', 'permissions': [PERMISSION_COMMENT_DELETE]}
comment_multiple_delete = {'text': _('delete'), 'view': 'comment_multiple_delete', 'args': 'object.pk', 'famfam': 'comments_delete', 'permissions': [PERMISSION_COMMENT_DELETE]} comment_multiple_delete = {'text': _('delete'), 'view': 'comment_multiple_delete', 'args': 'object.pk', 'famfam': 'comments_delete', 'permissions': [PERMISSION_COMMENT_DELETE]}
comment_add = {'text': _('add comment'), 'view': 'comment_add', 'args': 'object.pk', 'famfam': 'comment_add', 'permissions': [PERMISSION_COMMENT_CREATE]} comment_add = {'text': _('add comment'), 'view': 'comment_add', 'args': 'object.pk', 'famfam': 'comment_add', 'permissions': [PERMISSION_COMMENT_CREATE]}
+2 -2
View File
@@ -31,7 +31,7 @@ def comment_delete(request, comment_id=None, comment_id_list=None):
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_DELETE]) Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_DELETE])
except PermissionDenied: except PermissionDenied:
comments = AccessEntry.objects.filter_objects_by_access(PERMISSION_COMMENT_DELETE, request.user, comments, related='content_object') comments = AccessEntry.objects.filter_objects_by_access(PERMISSION_COMMENT_DELETE, request.user, comments, related='content_object')
if not comments: if not comments:
messages.error(request, _(u'Must provide at least one comment.')) messages.error(request, _(u'Must provide at least one comment.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
@@ -81,7 +81,7 @@ def comment_add(request, document_id):
Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_CREATE]) Permission.objects.check_permissions(request.user, [PERMISSION_COMMENT_CREATE])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_COMMENT_CREATE, request.user, document) AccessEntry.objects.check_access(PERMISSION_COMMENT_CREATE, request.user, document)
post_action_redirect = None post_action_redirect = None
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', '/')))
+1 -1
View File
@@ -40,7 +40,7 @@ def fs_create_document_link(index_instance, document, suffix=0):
if FILESERVING_ENABLE: if FILESERVING_ENABLE:
filename = assemble_suffixed_filename(document.file.name, suffix) filename = assemble_suffixed_filename(document.file.name, suffix)
filepath = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance), filename]) filepath = assemble_path_from_list([FILESERVING_PATH, get_instance_path(index_instance), filename])
try: try:
os.symlink(document.file.path, filepath) os.symlink(document.file.path, filepath)
except OSError, exc: except OSError, exc:
+4 -4
View File
@@ -6,16 +6,16 @@ from .conf.settings import SUFFIX_SEPARATOR
def assemble_suffixed_filename(filename, suffix=0): def assemble_suffixed_filename(filename, suffix=0):
''' """
Split document filename, to attach suffix to the name part then Split document filename, to attach suffix to the name part then
re attacht the extension re attacht the extension
''' """
if suffix: if suffix:
name, extension = filename.split(os.split(os.extsep)) name, extension = filename.split(os.split(os.extsep))
return SUFFIX_SEPARATOR.join([name, unicode(suffix), os.extsep, extension]) return SUFFIX_SEPARATOR.join([name, unicode(suffix), os.extsep, extension])
else: else:
return file_filename return filename
def assemble_path_from_list(directory_list): def assemble_path_from_list(directory_list):
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+1 -1
View File
@@ -59,7 +59,7 @@ def index_instance_list(request, index_id=None):
}, },
{ {
'name': _(u'items'), 'name': _(u'items'),
'attribute': encapsulate(lambda x: x.documents.count() if x.index.link_documents else x.get_children().count() ) 'attribute': encapsulate(lambda x: x.documents.count() if x.index.link_documents else x.get_children().count())
} }
], ],
'title': title, 'title': title,
+1 -1
View File
@@ -72,7 +72,7 @@ def document_post_save_hook(instance):
if not instance.pk: if not instance.pk:
document_signature, created = DocumentVersionSignature.objects.get_or_create( document_signature, created = DocumentVersionSignature.objects.get_or_create(
document_version=instance.latest_version, document_version=instance.latest_version,
) )
#DocumentVersionSignature.objects.update_signed_state(instance.document) #DocumentVersionSignature.objects.update_signed_state(instance.document)
#@receiver(post_save, dispatch_uid='check_document_signature_state', sender=DocumentVersion) #@receiver(post_save, dispatch_uid='check_document_signature_state', sender=DocumentVersion)
+7 -7
View File
@@ -13,12 +13,12 @@ class DocumentVersionSignatureManager(models.Manager):
document_signature, created = self.model.objects.get_or_create( document_signature, created = self.model.objects.get_or_create(
document_version=document.latest_version, document_version=document.latest_version,
) )
return document_signature return document_signature
def add_detached_signature(self, document, detached_signature): def add_detached_signature(self, document, detached_signature):
document_signature = self.get_document_signature(document) document_signature = self.get_document_signature(document)
if document_signature.has_embedded_signature: if document_signature.has_embedded_signature:
raise Exception('document already has an embedded signature') raise Exception('document already has an embedded signature')
else: else:
@@ -27,13 +27,13 @@ class DocumentVersionSignatureManager(models.Manager):
document_signature.delete_detached_signature() document_signature.delete_detached_signature()
document_signature.signature_file = None document_signature.signature_file = None
document_signature.save() document_signature.save()
document_signature.signature_file = detached_signature document_signature.signature_file = detached_signature
document_signature.save() document_signature.save()
def has_detached_signature(self, document): def has_detached_signature(self, document):
document_signature = self.get_document_signature(document) document_signature = self.get_document_signature(document)
if document_signature.signature_file: if document_signature.signature_file:
return True return True
else: else:
@@ -43,12 +43,12 @@ class DocumentVersionSignatureManager(models.Manager):
logger.debug('document: %s' % document) logger.debug('document: %s' % document)
document_signature = self.get_document_signature(document) document_signature = self.get_document_signature(document)
return document_signature.has_embedded_signature return document_signature.has_embedded_signature
def detached_signature(self, document): def detached_signature(self, document):
document_signature = self.get_document_signature(document) document_signature = self.get_document_signature(document)
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):
@@ -23,14 +23,10 @@ class Migration(DataMigration):
def backwards(self, orm): def backwards(self, orm):
for document_signature in orm.DocumentVersionSignature.objects.all(): for document_signature in orm.DocumentVersionSignature.objects.all():
try: document_version = document_signature.document_version
document_version = orm['documents.DocumentVersion'].objects.get(document_version=document_version) document_version.signature_state=document_signature.signature_state
except orm['documents.DocumentVersion'].DoesNotExists: document_version.signature_file=document_signature.signature_file
pass document_version.save()
else:
document_version.signature_state=document_signature.signature_state
document_version.signature_file=document_signature.signature_file
document_version.save()
models = { models = {
+3 -3
View File
@@ -14,9 +14,9 @@ logger = logging.getLogger(__name__)
class DocumentVersionSignature(models.Model): 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, storage=STORAGE_BACKEND(), 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)
@@ -28,7 +28,7 @@ class DocumentVersionSignature(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
if not self.pk: if not self.pk:
self.has_embedded_signature = gpg.has_embedded_signature(self.document_version.open(raw=True)) self.has_embedded_signature = gpg.has_embedded_signature(self.document_version.open(raw=True))
super(DocumentVersionSignature, self).save(*args, **kwargs) super(DocumentVersionSignature, self).save(*args, **kwargs)
class Meta: class Meta:
+1 -1
View File
@@ -117,7 +117,7 @@ def document_signature_download(request, document_pk):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SIGNATURE_DOWNLOAD]) Permission.objects.check_permissions(request.user, [PERMISSION_SIGNATURE_DOWNLOAD])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_SIGNATURE_DOWNLOAD, request.user, document) AccessEntry.objects.check_access(PERMISSION_SIGNATURE_DOWNLOAD, request.user, document)
try: try:
if DocumentVersionSignature.objects.has_detached_signature(document): if DocumentVersionSignature.objects.has_detached_signature(document):
+5 -3
View File
@@ -34,6 +34,8 @@ from .conf import settings as document_settings
from .widgets import document_thumbnail from .widgets import document_thumbnail
# Document page links expressions # Document page links expressions
def is_first_page(context): def is_first_page(context):
return context['page'].page_number <= 1 return context['page'].page_number <= 1
@@ -179,7 +181,7 @@ register_top_menu(
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_view_regex=[r'upload'],
children_views=['document_folder_list', 'folder_add_document', 'document_index_list', 'upload_version',], children_views=['document_folder_list', 'folder_add_document', 'document_index_list', 'upload_version', ],
position=1 position=1
) )
@@ -197,7 +199,7 @@ if (validate_path(document_settings.CACHE_PATH) == False) or (not document_setti
register_setup(document_type_setup) register_setup(document_type_setup)
class_permissions(Document, [ class_permissions(Document, [
PERMISSION_DOCUMENT_PROPERTIES_EDIT, PERMISSION_DOCUMENT_PROPERTIES_EDIT,
PERMISSION_DOCUMENT_EDIT, PERMISSION_DOCUMENT_EDIT,
PERMISSION_DOCUMENT_VIEW, PERMISSION_DOCUMENT_VIEW,
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DELETE,
@@ -205,5 +207,5 @@ class_permissions(Document, [
PERMISSION_DOCUMENT_TRANSFORM, PERMISSION_DOCUMENT_TRANSFORM,
PERMISSION_DOCUMENT_NEW_VERSION, PERMISSION_DOCUMENT_NEW_VERSION,
PERMISSION_DOCUMENT_VERSION_REVERT, PERMISSION_DOCUMENT_VERSION_REVERT,
PERMISSION_HISTORY_VIEW PERMISSION_HISTORY_VIEW
]) ])
+2 -2
View File
@@ -25,8 +25,8 @@ class DocumentVersionInline(admin.StackedInline):
#inlines = [ #inlines = [
# DocumentPageInline, # DocumentPageInline,
#] #]
class DocumentTypeFilenameInline(admin.StackedInline): class DocumentTypeFilenameInline(admin.StackedInline):
model = DocumentTypeFilename model = DocumentTypeFilename
extra = 1 extra = 1
+12 -12
View File
@@ -5,13 +5,11 @@ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext from django.utils.translation import ugettext
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.conf import settings
from common.forms import DetailForm from common.forms import DetailForm
from common.literals import PAGE_SIZE_CHOICES, PAGE_ORIENTATION_CHOICES from common.literals import PAGE_SIZE_CHOICES, PAGE_ORIENTATION_CHOICES
from common.conf.settings import DEFAULT_PAPER_SIZE from common.conf.settings import DEFAULT_PAPER_SIZE, DEFAULT_PAGE_ORIENTATION
from common.conf.settings import DEFAULT_PAGE_ORIENTATION from common.widgets import TextAreaDiv
from common.widgets import TextAreaDiv
from .models import (Document, DocumentType, from .models import (Document, DocumentType,
DocumentPage, DocumentPageTransformation, DocumentTypeFilename, DocumentPage, DocumentPageTransformation, DocumentTypeFilename,
@@ -19,6 +17,7 @@ from .models import (Document, DocumentType,
from .widgets import document_html_widget from .widgets import document_html_widget
from .literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES) from .literals import (RELEASE_LEVEL_FINAL, RELEASE_LEVEL_CHOICES)
# Document page forms # Document page forms
class DocumentPageTransformationForm(forms.ModelForm): class DocumentPageTransformationForm(forms.ModelForm):
class Meta: class Meta:
@@ -105,7 +104,7 @@ class DocumentPagesCarouselWidget(forms.widgets.Widget):
output.append(u'<div style="white-space:nowrap; overflow: auto;">') output.append(u'<div style="white-space:nowrap; overflow: auto;">')
for page in value.pages.all(): for page in value.pages.all():
output.append(u'<div style="display: inline-block; margin: 5px 10px 10px 10px;">') 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(u'<div class="tc">%(page_string)s %(page)s</div>' % {'page_string': ugettext(u'Page'), 'page': page.page_number})
output.append( output.append(
@@ -180,24 +179,24 @@ class DocumentForm(forms.ModelForm):
if instance: if instance:
self.version_fields(instance) self.version_fields(instance)
def version_fields(self, document): def version_fields(self, document):
self.fields['version_update'] = forms.ChoiceField( self.fields['version_update'] = forms.ChoiceField(
label=_(u'Version update'), label=_(u'Version update'),
choices=DocumentVersion.get_version_update_choices(document.latest_version) choices=DocumentVersion.get_version_update_choices(document.latest_version)
) )
self.fields['release_level'] = forms.ChoiceField( self.fields['release_level'] = forms.ChoiceField(
label=_(u'Release level'), label=_(u'Release level'),
choices=RELEASE_LEVEL_CHOICES, choices=RELEASE_LEVEL_CHOICES,
initial=RELEASE_LEVEL_FINAL, initial=RELEASE_LEVEL_FINAL,
) )
self.fields['serial'] = forms.IntegerField( self.fields['serial'] = forms.IntegerField(
label=_(u'Release level serial'), label=_(u'Release level serial'),
initial=0, initial=0,
widget=forms.widgets.TextInput( widget=forms.widgets.TextInput(
attrs = {'style': 'width: auto;'} attrs={'style': 'width: auto;'}
), ),
) )
@@ -210,7 +209,7 @@ class DocumentForm(forms.ModelForm):
new_filename = forms.CharField( new_filename = forms.CharField(
label=_('New document filename'), required=False label=_('New document filename'), required=False
) )
def clean(self): def clean(self):
cleaned_data = self.cleaned_data cleaned_data = self.cleaned_data
cleaned_data['new_version_data'] = { cleaned_data['new_version_data'] = {
@@ -221,7 +220,8 @@ class DocumentForm(forms.ModelForm):
} }
# Always return the full collection of cleaned data. # Always return the full collection of cleaned data.
return cleaned_data return cleaned_data
class DocumentForm_edit(DocumentForm): class DocumentForm_edit(DocumentForm):
""" """
@@ -230,7 +230,7 @@ class DocumentForm_edit(DocumentForm):
class Meta: class Meta:
model = Document model = Document
exclude = ('file', 'document_type', 'tags') exclude = ('file', 'document_type', 'tags')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(DocumentForm_edit, self).__init__(*args, **kwargs) super(DocumentForm_edit, self).__init__(*args, **kwargs)
self.fields.pop('serial') self.fields.pop('serial')
+1 -2
View File
@@ -4,7 +4,6 @@ from ast import literal_eval
from datetime import datetime from datetime import datetime
from django.db import models from django.db import models
from django.contrib.auth.models import AnonymousUser
from .conf.settings import RECENT_COUNT from .conf.settings import RECENT_COUNT
@@ -18,7 +17,7 @@ class RecentDocumentManager(models.Manager):
to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:] to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:]
for recent_to_delete in to_delete: for recent_to_delete in to_delete:
recent_to_delete.delete() recent_to_delete.delete()
def get_for_user(self, user): def get_for_user(self, user):
if user.is_authenticated(): if user.is_authenticated():
return [recent_document.document for recent_document in self.model.objects.filter(user=user)] return [recent_document.document for recent_document in self.model.objects.filter(user=user)]
+58 -58
View File
@@ -11,8 +11,8 @@ import logging
try: try:
from cStringIO import StringIO from cStringIO import StringIO
except ImportError: except ImportError:
from StringIO import StringIO from StringIO import StringIO
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext from django.utils.translation import ugettext
@@ -30,7 +30,7 @@ from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
DEFAULT_PAGE_NUMBER) DEFAULT_PAGE_NUMBER)
from .conf.settings import (CHECKSUM_FUNCTION, UUID_FUNCTION, from .conf.settings import (CHECKSUM_FUNCTION, UUID_FUNCTION,
STORAGE_BACKEND, PREVIEW_SIZE, DISPLAY_SIZE, CACHE_PATH, STORAGE_BACKEND, DISPLAY_SIZE, CACHE_PATH,
ZOOM_MAX_LEVEL, ZOOM_MIN_LEVEL) ZOOM_MAX_LEVEL, ZOOM_MIN_LEVEL)
from .managers import (RecentDocumentManager, from .managers import (RecentDocumentManager,
DocumentPageTransformationManager) DocumentPageTransformationManager)
@@ -70,9 +70,9 @@ class DocumentType(models.Model):
class Document(models.Model): class Document(models.Model):
''' """
Defines a single document with it's fields and properties Defines a single document with it's fields and properties
''' """
uuid = models.CharField(max_length=48, blank=True, editable=False) uuid = models.CharField(max_length=48, blank=True, editable=False)
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'), null=True, blank=True) 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')) description = models.TextField(blank=True, null=True, verbose_name=_(u'description'))
@@ -133,7 +133,7 @@ class Document(models.Model):
zoom = ZOOM_MAX_LEVEL zoom = ZOOM_MAX_LEVEL
rotation = rotation % 360 rotation = rotation % 360
try: try:
file_path = self.get_valid_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version) file_path = self.get_valid_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version)
except UnknownFileFormat: except UnknownFileFormat:
@@ -142,7 +142,7 @@ class Document(models.Model):
file_path = get_error_icon_file_path() file_path = get_error_icon_file_path()
except: except:
file_path = get_error_icon_file_path() file_path = get_error_icon_file_path()
if as_base64: if as_base64:
image = open(file_path, 'r') image = open(file_path, 'r')
out = StringIO() out = StringIO()
@@ -159,16 +159,16 @@ class Document(models.Model):
def add_as_recent_document_for_user(self, user): def add_as_recent_document_for_user(self, user):
RecentDocument.objects.add_document_for_user(user, self) RecentDocument.objects.add_document_for_user(user, self)
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
for version in self.versions.all(): for version in self.versions.all():
version.delete() version.delete()
return super(Document, self).delete(*args, **kwargs) return super(Document, self).delete(*args, **kwargs)
@property @property
def size(self): def size(self):
return self.latest_version.size return self.latest_version.size
def new_version(self, file, comment=None, version_update=None, release_level=None, serial=None): def new_version(self, file, comment=None, version_update=None, release_level=None, serial=None):
logger.debug('creating new document version') logger.debug('creating new document version')
if version_update: if version_update:
@@ -177,12 +177,12 @@ class Document(models.Model):
new_version = DocumentVersion( new_version = DocumentVersion(
document=self, document=self,
file=file, file=file,
major = new_version_dict.get('major'), major=new_version_dict.get('major'),
minor = new_version_dict.get('minor'), minor=new_version_dict.get('minor'),
micro = new_version_dict.get('micro'), micro=new_version_dict.get('micro'),
release_level = release_level, release_level=release_level,
serial = serial, serial=serial,
comment = comment, comment=comment,
) )
new_version.save() new_version.save()
else: else:
@@ -198,20 +198,20 @@ class Document(models.Model):
# Proxy methods # Proxy methods
def open(self, *args, **kwargs): def open(self, *args, **kwargs):
''' """
Return a file descriptor to a document's file irrespective of Return a file descriptor to a document's file irrespective of
the storage backend the storage backend
''' """
return self.latest_version.open(*args, **kwargs) return self.latest_version.open(*args, **kwargs)
def save_to_file(self, *args, **kwargs): def save_to_file(self, *args, **kwargs):
return self.latest_version.save_to_file(*args, **kwargs) return self.latest_version.save_to_file(*args, **kwargs)
def exists(self): 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 latest version file exists in storage
''' """
return self.latest_version.exists() return self.latest_version.exists()
# Compatibility methods # Compatibility methods
@@ -226,7 +226,7 @@ class Document(models.Model):
@property @property
def file_mime_encoding(self): def file_mime_encoding(self):
return self.latest_version.encoding return self.latest_version.encoding
@property @property
def file_filename(self): def file_filename(self):
return self.latest_version.filename return self.latest_version.filename
@@ -275,12 +275,12 @@ class Document(models.Model):
class DocumentVersion(models.Model): class DocumentVersion(models.Model):
''' """
Model that describes a document version and its properties Model that describes a document version and its properties
''' """
_pre_open_hooks = {} _pre_open_hooks = {}
_post_save_hooks = {} _post_save_hooks = {}
@staticmethod @staticmethod
def get_version_update_choices(document_version): def get_version_update_choices(document_version):
return ( return (
@@ -288,7 +288,7 @@ 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_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)) (VERSION_UPDATE_MICRO, _(u'Micro %(major)i.%(minor)i.%(micro)i, (fixes)') % document_version.get_new_version_dict(VERSION_UPDATE_MICRO))
) )
@classmethod @classmethod
def register_pre_open_hook(cls, order, func): def register_pre_open_hook(cls, order, func):
cls._pre_open_hooks[order] = func cls._pre_open_hooks[order] = func
@@ -296,7 +296,7 @@ class DocumentVersion(models.Model):
@classmethod @classmethod
def register_post_save_hook(cls, order, func): def register_post_save_hook(cls, order, func):
cls._post_save_hooks[order] = func cls._post_save_hooks[order] = func
document = models.ForeignKey(Document, verbose_name=_(u'document'), editable=False) document = models.ForeignKey(Document, verbose_name=_(u'document'), editable=False)
major = models.PositiveIntegerField(verbose_name=_(u'mayor'), default=1, editable=False) major = models.PositiveIntegerField(verbose_name=_(u'mayor'), default=1, editable=False)
minor = models.PositiveIntegerField(verbose_name=_(u'minor'), default=0, editable=False) minor = models.PositiveIntegerField(verbose_name=_(u'minor'), default=0, editable=False)
@@ -305,7 +305,7 @@ class DocumentVersion(models.Model):
serial = models.PositiveIntegerField(verbose_name=_(u'serial'), default=0, editable=False) serial = models.PositiveIntegerField(verbose_name=_(u'serial'), default=0, editable=False)
timestamp = models.DateTimeField(verbose_name=_(u'timestamp'), editable=False) timestamp = models.DateTimeField(verbose_name=_(u'timestamp'), editable=False)
comment = models.TextField(blank=True, verbose_name=_(u'comment')) comment = models.TextField(blank=True, verbose_name=_(u'comment'))
# File related fields # File related fields
file = models.FileField(upload_to=get_filename_from_uuid, storage=STORAGE_BACKEND(), verbose_name=_(u'file')) 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) mimetype = models.CharField(max_length=64, default='', editable=False)
@@ -342,11 +342,11 @@ class DocumentVersion(models.Model):
'minor': self.minor, 'minor': self.minor,
'micro': self.micro + 1, 'micro': self.micro + 1,
} }
def get_formated_version(self): def get_formated_version(self):
''' """
Return the formatted version information Return the formatted version information
''' """
vers = [u'%i.%i' % (self.major, self.minor), ] vers = [u'%i.%i' % (self.major, self.minor), ]
if self.micro: if self.micro:
@@ -360,10 +360,10 @@ class DocumentVersion(models.Model):
return self.documentpage_set return self.documentpage_set
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
''' """
Overloaded save method that updates the document version's checksum, Overloaded save method that updates the document version's checksum,
mimetype, page count and transformation when created mimetype, page count and transformation when created
''' """
new_document = not self.pk new_document = not self.pk
if not self.pk: if not self.pk:
self.timestamp = datetime.datetime.now() self.timestamp = datetime.datetime.now()
@@ -371,9 +371,9 @@ class DocumentVersion(models.Model):
#Only do this for new documents #Only do this for new documents
transformations = kwargs.pop('transformations', None) transformations = kwargs.pop('transformations', None)
super(DocumentVersion, self).save(*args, **kwargs) super(DocumentVersion, self).save(*args, **kwargs)
for key in sorted(DocumentVersion._post_save_hooks): for key in sorted(DocumentVersion._post_save_hooks):
DocumentVersion._post_save_hooks[key](self) DocumentVersion._post_save_hooks[key](self)
if new_document: if new_document:
#Only do this for new documents #Only do this for new documents
@@ -385,10 +385,10 @@ class DocumentVersion(models.Model):
self.apply_default_transformations(transformations) self.apply_default_transformations(transformations)
def update_checksum(self, save=True): def update_checksum(self, save=True):
''' """
Open a document version's file and update the checksum field using the Open a document version's file and update the checksum field using the
user provided checksum function user provided checksum function
''' """
if self.exists(): if self.exists():
source = self.open() source = self.open()
self.checksum = unicode(CHECKSUM_FUNCTION(source.read())) self.checksum = unicode(CHECKSUM_FUNCTION(source.read()))
@@ -444,17 +444,17 @@ class DocumentVersion(models.Model):
page_transformation.save() page_transformation.save()
def revert(self): def revert(self):
''' """
Delete the subsequent versions after this one Delete the subsequent versions after this one
''' """
for version in self.document.versions.filter(timestamp__gt=self.timestamp): for version in self.document.versions.filter(timestamp__gt=self.timestamp):
version.delete() version.delete()
def update_mimetype(self, save=True): def update_mimetype(self, save=True):
''' """
Read a document verions's file and determine the mimetype by calling the Read a document verions's file and determine the mimetype by calling the
get_mimetype wrapper get_mimetype wrapper
''' """
if self.exists(): if self.exists():
try: try:
self.mimetype, self.encoding = get_mimetype(self.open(), self.filename) self.mimetype, self.encoding = get_mimetype(self.open(), self.filename)
@@ -466,35 +466,35 @@ class DocumentVersion(models.Model):
self.save() self.save()
def delete(self, *args, **kwargs): 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) return super(DocumentVersion, self).delete(*args, **kwargs)
def exists(self): def exists(self):
''' """
Returns a boolean value that indicates if the document's file Returns a boolean value that indicates if the document's file
exists in storage exists in storage
''' """
return self.file.storage.exists(self.file.path) return self.file.storage.exists(self.file.path)
def open(self, raw=False): def open(self, raw=False):
''' """
Return a file descriptor to a document version's file irrespective of Return a file descriptor to a document version's file irrespective of
the storage backend the storage backend
''' """
if raw: if raw:
return self.file.storage.open(self.file.path) return self.file.storage.open(self.file.path)
else: else:
result = self.file.storage.open(self.file.path) result = self.file.storage.open(self.file.path)
for key in sorted(DocumentVersion._pre_open_hooks): for key in sorted(DocumentVersion._pre_open_hooks):
result = DocumentVersion._pre_open_hooks[key](result, self) result = DocumentVersion._pre_open_hooks[key](result, self)
return result return result
def save_to_file(self, filepath, buffer_size=1024 * 1024): def save_to_file(self, filepath, buffer_size=1024 * 1024):
''' """
Save a copy of the document from the document storage backend Save a copy of the document from the document storage backend
to the local filesystem to the local filesystem
''' """
input_descriptor = self.open() input_descriptor = self.open()
output_descriptor = open(filepath, 'wb') output_descriptor = open(filepath, 'wb')
while True: while True:
@@ -507,7 +507,7 @@ class DocumentVersion(models.Model):
output_descriptor.close() output_descriptor.close()
input_descriptor.close() input_descriptor.close()
return filepath return filepath
@property @property
def size(self): def size(self):
if self.exists(): if self.exists():
@@ -517,10 +517,10 @@ class DocumentVersion(models.Model):
class DocumentTypeFilename(models.Model): class DocumentTypeFilename(models.Model):
''' """
List of filenames available to a specific document type for the List of filenames available to a specific document type for the
quick rename functionality quick rename functionality
''' """
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type')) document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
filename = models.CharField(max_length=128, verbose_name=_(u'filename'), db_index=True) filename = models.CharField(max_length=128, verbose_name=_(u'filename'), db_index=True)
enabled = models.BooleanField(default=True, verbose_name=_(u'enabled')) enabled = models.BooleanField(default=True, verbose_name=_(u'enabled'))
@@ -535,12 +535,12 @@ class DocumentTypeFilename(models.Model):
class DocumentPage(models.Model): class DocumentPage(models.Model):
''' """
Model that describes a document version page including it's content Model that describes a document version page including it's content
''' """
# New parent field # New parent field
document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version')) document_version = models.ForeignKey(DocumentVersion, verbose_name=_(u'document version'))
# Unchanged fields # Unchanged fields
content = models.TextField(blank=True, null=True, verbose_name=_(u'content')) 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_label = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u'page label'))
@@ -568,7 +568,7 @@ class DocumentPage(models.Model):
@property @property
def siblings(self): def siblings(self):
return DocumentPage.objects.filter(document_version=self.document_version) return DocumentPage.objects.filter(document_version=self.document_version)
# Compatibility methods # Compatibility methods
@property @property
def document(self): def document(self):
+15 -17
View File
@@ -3,7 +3,6 @@ from __future__ import absolute_import
import os import os
from django.utils import unittest from django.utils import unittest
from django.test.client import Client
from django.conf import settings from django.conf import settings
from django.core.files.base import File from django.core.files.base import File
@@ -19,45 +18,45 @@ class DocumentTestCase(unittest.TestCase):
self.document_type.save() self.document_type.save()
self.document = Document( self.document = Document(
document_type = self.document_type, document_type=self.document_type,
description = 'description', description='description',
) )
self.document.save() self.document.save()
#return File(file(self.filepath, 'rb'), name=self.filename) #return File(file(self.filepath, 'rb'), name=self.filename)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf')) 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')) new_version = self.document.new_version(file=File(file_object, name='mayan_11_1.pdf'))
file_object.close() file_object.close()
def runTest(self): def runTest(self):
self.failUnlessEqual(self.document_type.name, 'test doc type') self.failUnlessEqual(self.document_type.name, 'test doc type')
self.failUnlessEqual(self.document.exists(), True) self.failUnlessEqual(self.document.exists(), True)
self.failUnlessEqual(self.document.size, 272213) self.failUnlessEqual(self.document.size, 272213)
self.failUnlessEqual(self.document.file_mimetype, 'application/pdf') self.failUnlessEqual(self.document.file_mimetype, 'application/pdf')
self.failUnlessEqual(self.document.file_mime_encoding, 'binary') self.failUnlessEqual(self.document.file_mime_encoding, 'binary')
self.failUnlessEqual(self.document.file_filename, 'mayan_11_1.pdf') self.failUnlessEqual(self.document.file_filename, 'mayan_11_1.pdf')
self.failUnlessEqual(self.document.checksum, 'c637ffab6b8bb026ed3784afdb07663fddc60099853fae2be93890852a69ecf3') self.failUnlessEqual(self.document.checksum, 'c637ffab6b8bb026ed3784afdb07663fddc60099853fae2be93890852a69ecf3')
self.failUnlessEqual(self.document.page_count, 47) self.failUnlessEqual(self.document.page_count, 47)
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '1.0') self.failUnlessEqual(self.document.latest_version.get_formated_version(), '1.0')
self.failUnlessEqual(self.document.has_detached_signature(), False) self.failUnlessEqual(self.document.has_detached_signature(), False)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf.gpg')) file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf.gpg'))
new_version_data = { new_version_data = {
'comment': 'test comment 1', 'comment': 'test comment 1',
'version_update': VERSION_UPDATE_MAJOR, 'version_update': VERSION_UPDATE_MAJOR,
'release_level': RELEASE_LEVEL_FINAL, 'release_level': RELEASE_LEVEL_FINAL,
'serial': 0, 'serial': 0,
} }
new_version = self.document.new_version(file=File(file_object, name='mayan_11_1.pdf.gpg'), **new_version_data) new_version = self.document.new_version(file=File(file_object, name='mayan_11_1.pdf.gpg'), **new_version_data)
file_object.close() file_object.close()
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '2.0') self.failUnlessEqual(self.document.latest_version.get_formated_version(), '2.0')
self.failUnlessEqual(self.document.has_detached_signature(), False) self.failUnlessEqual(self.document.has_detached_signature(), False)
self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID) self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID)
new_version_data = { new_version_data = {
@@ -65,23 +64,22 @@ class DocumentTestCase(unittest.TestCase):
'version_update': VERSION_UPDATE_MAJOR, 'version_update': VERSION_UPDATE_MAJOR,
'release_level': RELEASE_LEVEL_FINAL, 'release_level': RELEASE_LEVEL_FINAL,
'serial': 0, 'serial': 0,
} }
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf')) 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) new_version = self.document.new_version(file=File(file_object), **new_version_data)
file_object.close() file_object.close()
self.failUnlessEqual(self.document.latest_version.get_formated_version(), '3.0') self.failUnlessEqual(self.document.latest_version.get_formated_version(), '3.0')
#GPGVerificationError #GPGVerificationError
self.failUnlessEqual(self.document.verify_signature(), None) self.failUnlessEqual(self.document.verify_signature(), None)
file_object = open(os.path.join(settings.PROJECT_ROOT, 'contrib', 'mayan_11_1.pdf.sig'), 'rb') 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)) new_version = self.document.add_detached_signature(File(file_object))
file_object.close() file_object.close()
self.failUnlessEqual(self.document.has_detached_signature(), True) self.failUnlessEqual(self.document.has_detached_signature(), True)
self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID) self.failUnlessEqual(self.document.verify_signature().status, SIGNATURE_STATE_VALID)
def tearDown(self): def tearDown(self):
self.document.delete() self.document.delete()
+1 -1
View File
@@ -33,7 +33,7 @@ urlpatterns = patterns('documents.views',
url(r'^(?P<document_id>\d+)/create/siblings/$', 'document_create_siblings', (), 'document_create_siblings'), 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+)/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_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'^(?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+)/download/$', 'document_download', (), 'document_version_download'),
url(r'^document/version/(?P<document_version_pk>\d+)/revert/$', 'document_version_revert', (), 'document_version_revert'), url(r'^document/version/(?P<document_version_pk>\d+)/revert/$', 'document_version_revert', (), 'document_version_revert'),
+50 -50
View File
@@ -48,10 +48,10 @@ from .literals import (HISTORY_DOCUMENT_CREATED,
HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED) HISTORY_DOCUMENT_EDITED, HISTORY_DOCUMENT_DELETED)
from .forms import (DocumentTypeSelectForm, from .forms import (DocumentTypeSelectForm,
DocumentForm_edit, DocumentPropertiesForm, DocumentForm_edit, DocumentPropertiesForm,
DocumentPreviewForm, DocumentPageForm, DocumentPreviewForm, DocumentPageForm,
DocumentPageTransformationForm, DocumentContentForm, DocumentPageTransformationForm, DocumentContentForm,
DocumentPageForm_edit, DocumentPageForm_text, PrintForm, DocumentPageForm_edit, DocumentPageForm_text, PrintForm,
DocumentTypeForm, DocumentTypeFilenameForm, DocumentTypeForm, DocumentTypeFilenameForm,
DocumentTypeFilenameForm_create) DocumentTypeFilenameForm_create)
from .wizards import DocumentCreateWizard from .wizards import DocumentCreateWizard
from .models import (Document, DocumentType, DocumentPage, from .models import (Document, DocumentType, DocumentPage,
@@ -68,12 +68,12 @@ def document_list(request, object_list=None, title=None, extra_context=None):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
# If user doesn't have global permission, get a list of document # If user doesn't have global permission, get a list of document
# for which he/she does hace access use it to filter the # for which he/she does hace access use it to filter the
# provided object_list # provided object_list
final_object_list = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_VIEW, request.user, pre_object_list) final_object_list = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_VIEW, request.user, pre_object_list)
else: else:
final_object_list = pre_object_list final_object_list = pre_object_list
context = { context = {
'object_list': final_object_list, 'object_list': final_object_list,
'title': title if title else _(u'documents'), 'title': title if title else _(u'documents'),
@@ -190,7 +190,7 @@ def document_delete(request, document_id=None, document_id_list=None):
documents = [get_object_or_404(Document, pk=document_id)] documents = [get_object_or_404(Document, pk=document_id)]
post_action_redirect = reverse('document_list') post_action_redirect = reverse('document_list')
elif document_id_list: elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')] documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
else: else:
messages.error(request, _(u'Must provide at least one document.')) messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
@@ -296,12 +296,12 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, base64_version=F
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document)
page = int(request.GET.get('page', DEFAULT_PAGE_NUMBER)) page = int(request.GET.get('page', DEFAULT_PAGE_NUMBER))
zoom = int(request.GET.get('zoom', DEFAULT_ZOOM_LEVEL)) zoom = int(request.GET.get('zoom', DEFAULT_ZOOM_LEVEL))
version = int(request.GET.get('version', document.latest_version.pk)) version = int(request.GET.get('version', document.latest_version.pk))
if zoom < ZOOM_MIN_LEVEL: if zoom < ZOOM_MIN_LEVEL:
@@ -317,12 +317,12 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, base64_version=F
else: else:
# TODO: fix hardcoded MIMETYPE # TODO: fix hardcoded MIMETYPE
return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE) return sendfile.sendfile(request, document.get_image(size=size, page=page, zoom=zoom, rotation=rotation, version=version), mimetype=DEFAULT_FILE_FORMAT_MIMETYPE)
def document_download(request, document_id=None, document_id_list=None, document_version_pk=None): def document_download(request, document_id=None, document_id_list=None, document_version_pk=None):
document_version = None document_version = None
documents = [] documents = []
if document_id: if document_id:
documents = [get_object_or_404(Document, pk=document_id)] documents = [get_object_or_404(Document, pk=document_id)]
post_action_redirect = reverse('document_list') post_action_redirect = reverse('document_list')
@@ -338,7 +338,7 @@ def document_download(request, document_id=None, document_id_list=None, document
if len(documents) == 1: if len(documents) == 1:
document_version = documents[0].latest_version document_version = documents[0].latest_version
if document_version: if document_version:
try: try:
# Test permissions and trigger exception # Test permissions and trigger exception
@@ -363,9 +363,9 @@ def document_download(request, document_id=None, document_id_list=None, document
descriptor = document.open() descriptor = document.open()
compressed_file.add_file(descriptor, arcname=document.filename) compressed_file.add_file(descriptor, arcname=document.filename)
descriptor.close() descriptor.close()
compressed_file.close() compressed_file.close()
return serve_file( return serve_file(
request, request,
compressed_file.as_file('document_bundle.zip'), compressed_file.as_file('document_bundle.zip'),
@@ -386,14 +386,14 @@ def document_multiple_download(request):
request, document_id_list=request.GET.get('id_list', []) request, document_id_list=request.GET.get('id_list', [])
) )
def document_page_transformation_list(request, document_page_id): def document_page_transformation_list(request, document_page_id):
document_page = get_object_or_404(DocumentPage, pk=document_page_id) document_page = get_object_or_404(DocumentPage, pk=document_page_id)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page.document)
return object_list( return object_list(
request, request,
@@ -418,11 +418,11 @@ def document_page_transformation_list(request, document_page_id):
def document_page_transformation_create(request, document_page_id): def document_page_transformation_create(request, document_page_id):
document_page = get_object_or_404(DocumentPage, pk=document_page_id) document_page = get_object_or_404(DocumentPage, pk=document_page_id)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page.document)
if request.method == 'POST': if request.method == 'POST':
form = DocumentPageTransformationForm(request.POST, initial={'document_page': document_page}) form = DocumentPageTransformationForm(request.POST, initial={'document_page': document_page})
@@ -450,7 +450,7 @@ def document_page_transformation_edit(request, document_page_transformation_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page_transformation.document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page_transformation.document_page.document)
if request.method == 'POST': if request.method == 'POST':
form = DocumentPageTransformationForm(request.POST, instance=document_page_transformation) form = DocumentPageTransformationForm(request.POST, instance=document_page_transformation)
@@ -482,7 +482,7 @@ def document_page_transformation_delete(request, document_page_transformation_id
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TRANSFORM])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page_transformation.document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_TRANSFORM, request.user, document_page_transformation.document_page.document)
redirect_view = reverse('document_page_transformation_list', args=[document_page_transformation.document_page_id]) redirect_view = reverse('document_page_transformation_list', args=[document_page_transformation.document_page_id])
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', redirect_view)))
@@ -516,7 +516,7 @@ def document_find_duplicates(request, document_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document)
extra_context = { extra_context = {
'title': _(u'duplicates of: %s') % document, 'title': _(u'duplicates of: %s') % document,
@@ -565,8 +565,8 @@ def document_find_all_duplicates(request):
def document_update_page_count(request): def document_update_page_count(request):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TOOLS]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TOOLS])
office_converter = OfficeConverter() office_converter = OfficeConverter()
qs = DocumentVersion.objects.exclude(filename__iendswith='dxf').filter(mimetype__in=office_converter.mimetypes()) qs = DocumentVersion.objects.exclude(filename__iendswith='dxf').filter(mimetype__in=office_converter.mimetypes())
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
@@ -580,7 +580,7 @@ def document_update_page_count(request):
processed += 1 processed += 1
if old_page_count != document_version.pages.count(): if old_page_count != document_version.pages.count():
updated += 1 updated += 1
messages.success(request, _(u'Page count update complete. Documents processed: %(total)d, documents with changed page count: %(change)d') % { messages.success(request, _(u'Page count update complete. Documents processed: %(total)d, documents with changed page count: %(change)d') % {
'total': processed, 'total': processed,
'change': updated 'change': updated
@@ -673,12 +673,12 @@ def document_missing_list(request):
def document_page_view(request, document_page_id): def document_page_view(request, document_page_id):
document_page = get_object_or_404(DocumentPage, pk=document_page_id) document_page = get_object_or_404(DocumentPage, pk=document_page_id)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
zoom = int(request.GET.get('zoom', DEFAULT_ZOOM_LEVEL)) zoom = int(request.GET.get('zoom', DEFAULT_ZOOM_LEVEL))
rotation = int(request.GET.get('rotation', DEFAULT_ROTATION)) rotation = int(request.GET.get('rotation', DEFAULT_ROTATION))
@@ -717,7 +717,7 @@ def document_page_text(request, document_page_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
document_page_form = DocumentPageForm_text(instance=document_page) document_page_form = DocumentPageForm_text(instance=document_page)
@@ -733,11 +733,11 @@ def document_page_text(request, document_page_id):
def document_page_edit(request, document_page_id): def document_page_edit(request, document_page_id):
document_page = get_object_or_404(DocumentPage, pk=document_page_id) document_page = get_object_or_404(DocumentPage, pk=document_page_id)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_EDIT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_EDIT, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_EDIT, request.user, document_page.document)
if request.method == 'POST': if request.method == 'POST':
form = DocumentPageForm_edit(request.POST, instance=document_page) form = DocumentPageForm_edit(request.POST, instance=document_page)
@@ -766,8 +766,8 @@ def document_page_navigation_next(request, document_page_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path) view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
if document_page.page_number >= document_page.siblings.count(): if document_page.page_number >= document_page.siblings.count():
@@ -784,7 +784,7 @@ def document_page_navigation_previous(request, document_page_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path) view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
@@ -803,7 +803,7 @@ def document_page_navigation_first(request, document_page_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path) view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
@@ -812,12 +812,12 @@ def document_page_navigation_first(request, document_page_id):
def document_page_navigation_last(request, document_page_id): def document_page_navigation_last(request, document_page_id):
document_page = get_object_or_404(DocumentPage, pk=document_page_id) document_page = get_object_or_404(DocumentPage, pk=document_page_id)
document_page = get_object_or_404(document_page.siblings, page_number=document_page.siblings.count()) document_page = get_object_or_404(document_page.siblings, page_number=document_page.siblings.count())
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path) view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
@@ -841,7 +841,7 @@ def transform_page(request, document_page_id, zoom_function=None, rotation_funct
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document_page.document)
view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path) view = resolve_to_name(urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).path)
@@ -900,11 +900,11 @@ def document_page_rotate_left(request, document_page_id):
def document_print(request, document_id): def document_print(request, document_id):
document = get_object_or_404(Document, pk=document_id) document = get_object_or_404(Document, pk=document_id)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document)
RecentDocument.objects.add_document_for_user(request.user, document) RecentDocument.objects.add_document_for_user(request.user, document)
@@ -964,7 +964,7 @@ def document_hard_copy(request, document_id):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document)
RecentDocument.objects.add_document_for_user(request.user, document) RecentDocument.objects.add_document_for_user(request.user, document)
@@ -1056,7 +1056,7 @@ def document_type_edit(request, document_type_id):
#'object': document_type, #'object': document_type,
'object_name': _(u'document type'), 'object_name': _(u'document type'),
'navigation_object_name': 'document_type', 'navigation_object_name': 'document_type',
'document_type': document_type, 'document_type': document_type,
'next': next 'next': next
}, },
context_instance=RequestContext(request)) context_instance=RequestContext(request))
@@ -1253,8 +1253,8 @@ def document_type_filename_create(request, document_type_id):
'document_type': document_type, 'document_type': document_type,
}, },
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def document_clear_image_cache(request): def document_clear_image_cache(request):
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TOOLS]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_TOOLS])
@@ -1266,23 +1266,23 @@ def document_clear_image_cache(request):
messages.success(request, _(u'Document image cache cleared successfully')) messages.success(request, _(u'Document image cache cleared successfully'))
except Exception, msg: except Exception, msg:
messages.error(request, _(u'Error clearing document image cache; %s') % msg) messages.error(request, _(u'Error clearing document image cache; %s') % msg)
return HttpResponseRedirect(previous) return HttpResponseRedirect(previous)
return render_to_response('generic_confirm.html', { return render_to_response('generic_confirm.html', {
'previous': previous, 'previous': previous,
'title': _(u'Are you sure you wish to clear the document image cache?'), 'title': _(u'Are you sure you wish to clear the document image cache?'),
'form_icon': u'camera_delete.png', 'form_icon': u'camera_delete.png',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def document_version_list(request, document_pk): def document_version_list(request, document_pk):
document = get_object_or_404(Document, pk=document_pk) document = get_object_or_404(Document, pk=document_pk)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VIEW, request.user, document)
RecentDocument.objects.add_document_for_user(request.user, document) RecentDocument.objects.add_document_for_user(request.user, document)
@@ -1330,7 +1330,7 @@ def document_version_revert(request, document_version_pk):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VERSION_REVERT]) Permission.objects.check_permissions(request.user, [PERMISSION_DOCUMENT_VERSION_REVERT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VERSION_REVERT, request.user, document_version.document) AccessEntry.objects.check_access(PERMISSION_DOCUMENT_VERSION_REVERT, request.user, document_version.document)
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
@@ -1340,7 +1340,7 @@ def document_version_revert(request, document_version_pk):
messages.success(request, _(u'Document version reverted successfully')) messages.success(request, _(u'Document version reverted successfully'))
except Exception, msg: except Exception, msg:
messages.error(request, _(u'Error reverting document version; %s') % msg) messages.error(request, _(u'Error reverting document version; %s') % msg)
return HttpResponseRedirect(previous) return HttpResponseRedirect(previous)
return render_to_response('generic_confirm.html', { return render_to_response('generic_confirm.html', {
@@ -1349,4 +1349,4 @@ def document_version_revert(request, document_version_pk):
'title': _(u'Are you sure you wish to revert to this version?'), 'title': _(u'Are you sure you wish to revert to this version?'),
'message': _(u'All later version after this one will be deleted too.'), 'message': _(u'All later version after this one will be deleted too.'),
'form_icon': u'page_refresh.png', 'form_icon': u'page_refresh.png',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
+7 -10
View File
@@ -6,12 +6,9 @@ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.http import urlencode from django.utils.http import urlencode
from converter.literals import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, \ from converter.literals import (DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION,
DEFAULT_PAGE_NUMBER DEFAULT_PAGE_NUMBER)
from converter.exceptions import UnknownFileFormat, UnkownConvertError
from mimetype.api import get_error_icon_url from mimetype.api import get_error_icon_url
from .conf.settings import DISPLAY_SIZE
def document_thumbnail(document): def document_thumbnail(document):
@@ -24,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): 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 = [] result = []
alt_text = _(u'document page image') alt_text = _(u'document page image')
if not version: if not version:
@@ -41,13 +38,13 @@ def document_html_widget(document, view='document_thumbnail', click_view=None, p
gallery_template = u'rel="%s"' % gallery_name gallery_template = u'rel="%s"' % gallery_name
else: else:
gallery_template = u'' gallery_template = u''
query_string = urlencode(query_dict) query_string = urlencode(query_dict)
preview_view = u'%s?%s' % (reverse(view, args=[document.pk]), query_string) preview_view = u'%s?%s' % (reverse(view, args=[document.pk]), query_string)
plain_template = [] plain_template = []
plain_template.append(u'<img src="%s" alt="%s" />' % (preview_view, alt_text)) 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)) result.append(u'<div class="tc" id="document-%d-%d">' % (document.pk, page if page else 1))
if click_view: if click_view:
@@ -55,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'<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)) 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'</a>')
result.append(u'</div>') result.append(u'</div>')
View File
-3
View File
@@ -1,3 +0,0 @@
from django.db import models
# Create your models here.
-16
View File
@@ -1,16 +0,0 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)
-5
View File
@@ -1,5 +0,0 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('exporter.views',
url(r'^export_test/$', 'export_test', (), 'export_test'),
)
-150
View File
@@ -1,150 +0,0 @@
import os
import hashlib
from django.utils import simplejson
from django.http import HttpResponse
from django.template.defaultfilters import slugify
from documents.models import Document, DocumentType
from metadata.models import MetadataType, MetadataSet
FORMAT_VERSION = 1.0
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
def get_hash(obj):
if obj:
return u'%s_%s' % (HASH_FUNCTION(unicode(obj)), slugify(unicode(obj)))
else:
return None
'''
comments
tags
folders
pages
pages transformation
metadata
doc_type metadata
sources
sources transform
users
class DocumentTypeDefaults(models.Model):
"""
Default preselected metadata types and metadata set per document
type
"""
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
default_metadata_sets = models.ManyToManyField(MetadataSet, blank=True, verbose_name=_(u'default metadata sets'))
default_metadata = models.ManyToManyField(MetadataType, blank=True, verbose_name=_(u'default metadata'))
'''
def export_test(request):
big_list = []
big_list.append({'version': FORMAT_VERSION})
for metadata_type in MetadataType.objects.all():
big_list.append(
{
'metadata_types': [
{
'id': get_hash(metadata_type.name),
'name': metadata_type.name,
'title': metadata_type.title,
'default': metadata_type.default,
'lookup': metadata_type.lookup,
}
]
}
)
for metadata_set in MetadataSet.objects.all():
big_list.append(
{
'metadata_sets': [
{
'id': get_hash(metadata_set.title),
'name': metadata_set.title,
'metadata_types': [
{
'id': get_hash(metadata_type),
}
for metadata_type in metadata_set.metadatasetitem_set.all()
]
}
]
}
)
for document_type in DocumentType.objects.all():
big_list.append(
{
'document_types': [
{
'id': get_hash(document_type.name),
'name': document_type.name,
'filenames': [
{
'filename': doc_type_filename.filename,
'enabled': doc_type_filename.enabled,
}
for doc_type_filename in document_type.documenttypefilename_set.all()
],
'metadata_defaults': [
{
'default_metadata': [get_hash(metadata_type.name) for metadata_type in doc_type_defaults.default_metadata.all()],
'default_metadata_sets': [get_hash(metadata_set.title) for metadata_set in doc_type_defaults.default_metadata_sets.all()],
}
for doc_type_defaults in document_type.documenttypedefaults_set.all()
]
}
]
}
)
for document in Document.objects.all()[:10]:
big_list.append(
{
'documents': [
{
'document_type': get_hash(document.document_type),
'filename': os.extsep.join([document.file_filename, document.file_extension]),
#'date_added'
'uuid': document.uuid,
'description': unicode(document.description) if document.description else None,
'tags': [get_hash(tag) for tag in document.tags.all()],
'folders': [get_hash(folder_document.folder) for folder_document in document.folderdocument_set.all()],
'comments': [
{
'comment': comment.comment,
'user': unicode(comment.user),
'submit_date': unicode(comment.submit_date),
}
for comment in document.comments.all()
],
'versions': [
{
1.0: {
'mimetype': document.file_mimetype,
'encoding': document.file_mime_encoding,
#'date_updated'
'checksum': document.checksum,
}
}
]
}
]
}
)
return HttpResponse(simplejson.dumps(big_list, indent=4, ensure_ascii=True), mimetype='application/json')
+1 -1
View File
@@ -32,7 +32,7 @@ class FolderListForm(forms.Form):
Permission.objects.check_permissions(user, [PERMISSION_FOLDER_VIEW]) Permission.objects.check_permissions(user, [PERMISSION_FOLDER_VIEW])
except PermissionDenied: except PermissionDenied:
queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_FOLDER_VIEW, user, queryset) queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_FOLDER_VIEW, user, queryset)
self.fields['folder'] = forms.ModelChoiceField( self.fields['folder'] = forms.ModelChoiceField(
queryset=queryset, queryset=queryset,
label=_(u'Folder')) label=_(u'Folder'))
+3 -3
View File
@@ -23,15 +23,15 @@ class Folder(models.Model):
@models.permalink @models.permalink
def get_absolute_url(self): def get_absolute_url(self):
return ('folder_view', [self.pk]) return ('folder_view', [self.pk])
@property @property
def documents(self): def documents(self):
return [folder_document.document for folder_document in self.folderdocument_set.all()] return [folder_document.document for folder_document in self.folderdocument_set.all()]
def remove_document(self, document): def remove_document(self, document):
folder_document = self.folderdocument_set.get(document=document) folder_document = self.folderdocument_set.get(document=document)
folder_document.delete() folder_document.delete()
def add_document(self, document): def add_document(self, document):
folder_document, created = FolderDocument.objects.get_or_create(folder=self, document=document) folder_document, created = FolderDocument.objects.get_or_create(folder=self, document=document)
return created return created
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
-23
View File
@@ -1,23 +0,0 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}
+1 -1
View File
@@ -11,6 +11,6 @@ urlpatterns = patterns('folders.views',
url(r'^document/(?P<document_id>\d+)/folder/add/$', 'folder_add_document', (), 'folder_add_document'), url(r'^document/(?P<document_id>\d+)/folder/add/$', 'folder_add_document', (), 'folder_add_document'),
url(r'^document/(?P<document_id>\d+)/folder/list/$', 'document_folder_list', (), 'document_folder_list'), url(r'^document/(?P<document_id>\d+)/folder/list/$', 'document_folder_list', (), 'document_folder_list'),
url(r'^(?P<folder_pk>\d+)/acl/list/$', 'folder_acl_list', (), 'folder_acl_list'), url(r'^(?P<folder_pk>\d+)/acl/list/$', 'folder_acl_list', (), 'folder_acl_list'),
) )
+8 -10
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
@@ -7,7 +7,6 @@ from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response, get_object_or_404 from django.shortcuts import render_to_response, get_object_or_404
from django.template import RequestContext from django.template import RequestContext
from django.contrib import messages from django.contrib import messages
from django.views.generic.list_detail import object_list
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
@@ -19,7 +18,7 @@ from common.utils import encapsulate
from acls.models import AccessEntry from acls.models import AccessEntry
from acls.views import acl_list_for from acls.views import acl_list_for
from .models import Folder, FolderDocument from .models import Folder
from .forms import FolderForm, FolderListForm from .forms import FolderForm, FolderListForm
from .permissions import (PERMISSION_FOLDER_CREATE, from .permissions import (PERMISSION_FOLDER_CREATE,
PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_DELETE, PERMISSION_FOLDER_EDIT, PERMISSION_FOLDER_DELETE,
@@ -50,8 +49,8 @@ def folder_list(request, queryset=None, extra_context=None):
queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_FOLDER_VIEW, request.user, queryset) queryset = AccessEntry.objects.filter_objects_by_access(PERMISSION_FOLDER_VIEW, request.user, queryset)
context['object_list'] = queryset context['object_list'] = queryset
return render_to_response('generic_list.html', return render_to_response('generic_list.html',
context, context,
context_instance=RequestContext(request) context_instance=RequestContext(request)
) )
@@ -59,7 +58,7 @@ def folder_list(request, queryset=None, extra_context=None):
def folder_create(request): def folder_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_FOLDER_CREATE]) Permission.objects.check_permissions(request.user, [PERMISSION_FOLDER_CREATE])
if request.method == 'POST': if request.method == 'POST':
form = FolderForm(request.POST) form = FolderForm(request.POST)
if form.is_valid(): if form.is_valid():
@@ -158,9 +157,9 @@ def folder_view(request, folder_id):
'hide_links': True, 'hide_links': True,
'multi_select_as_buttons': True, 'multi_select_as_buttons': True,
'object': folder, 'object': folder,
'object_name': _(u'folder'), 'object_name': _(u'folder'),
} }
return document_list( return document_list(
request, request,
object_list=folder.documents, object_list=folder.documents,
@@ -194,14 +193,13 @@ def folder_add_document(request, document_id):
else: else:
form = FolderListForm(user=request.user) form = FolderListForm(user=request.user)
return render_to_response('generic_form.html', { return render_to_response('generic_form.html', {
'title': _(u'add document "%s" to a folder') % document, 'title': _(u'add document "%s" to a folder') % document,
'form': form, 'form': form,
'object': document, 'object': document,
'next': next, 'next': next,
}, },
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def document_folder_list(request, document_id): def document_folder_list(request, document_id):
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.contrib import admin from django.contrib import admin
+5 -5
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@@ -18,7 +18,7 @@ class SmartLinkForm(forms.ModelForm):
class Meta: class Meta:
model = SmartLink model = SmartLink
class SmartLinkConditionForm(forms.ModelForm): class SmartLinkConditionForm(forms.ModelForm):
class Meta: class Meta:
model = SmartLinkCondition model = SmartLinkCondition
@@ -56,7 +56,7 @@ class SmartLinkImageWidget(forms.widgets.Widget):
output.append(u'<a href="%s"><span class="famfam active famfam-page_go"></span>%s</a>' % (reverse('document_view_simple', args=[document.pk]), ugettext(u'Select'))) output.append(u'<a href="%s"><span class="famfam active famfam-page_go"></span>%s</a>' % (reverse('document_view_simple', args=[document.pk]), ugettext(u'Select')))
output.append(u'</div>') output.append(u'</div>')
output.append(u'</div>') output.append(u'</div>')
output.append(u'</div>') output.append(u'</div>')
output.append( output.append(
u'<br /><span class="famfam active famfam-magnifier"></span>%s' % u'<br /><span class="famfam active famfam-magnifier"></span>%s' %
@@ -70,9 +70,9 @@ class SmartLinkInstanceForm(forms.Form):
smart_link_instances = kwargs.pop('smart_link_instances', None) smart_link_instances = kwargs.pop('smart_link_instances', None)
links = kwargs.pop('links', None) links = kwargs.pop('links', None)
current_document = kwargs.pop('current_document', None) current_document = kwargs.pop('current_document', None)
super(SmartLinkInstanceForm, self).__init__(*args, **kwargs) super(SmartLinkInstanceForm, self).__init__(*args, **kwargs)
for smart_link_instance, data in smart_link_instances.items(): for smart_link_instance, data in smart_link_instances.items():
self.fields['preview-%s' % smart_link_instance] = forms.CharField( self.fields['preview-%s' % smart_link_instance] = forms.CharField(
widget=SmartLinkImageWidget(), widget=SmartLinkImageWidget(),
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.db import models from django.db import models
from django.db.models import Q from django.db.models import Q
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
+2 -2
View File
@@ -4,12 +4,12 @@ urlpatterns = patterns('linking.views',
url(r'^action/$', 'smart_link_action', (), 'smart_link_action'), url(r'^action/$', 'smart_link_action', (), 'smart_link_action'),
url(r'^document/(?P<document_id>\d+)/smart_link/(?P<smart_link_pk>\d+)/$', 'smart_link_instance_view', (), 'smart_link_instance_view'), url(r'^document/(?P<document_id>\d+)/smart_link/(?P<smart_link_pk>\d+)/$', 'smart_link_instance_view', (), 'smart_link_instance_view'),
url(r'^smart/for_document/(?P<document_id>\d+)/$', 'smart_link_instances_for_document', (), 'smart_link_instances_for_document'), url(r'^smart/for_document/(?P<document_id>\d+)/$', 'smart_link_instances_for_document', (), 'smart_link_instances_for_document'),
url(r'^setup/list/$', 'smart_link_list', (), 'smart_link_list'), url(r'^setup/list/$', 'smart_link_list', (), 'smart_link_list'),
url(r'^setup/create/$', 'smart_link_create', (), 'smart_link_create'), url(r'^setup/create/$', 'smart_link_create', (), 'smart_link_create'),
url(r'^setup/(?P<smart_link_pk>\d+)/delete/$', 'smart_link_delete', (), 'smart_link_delete'), url(r'^setup/(?P<smart_link_pk>\d+)/delete/$', 'smart_link_delete', (), 'smart_link_delete'),
url(r'^setup/(?P<smart_link_pk>\d+)/edit/$', 'smart_link_edit', (), 'smart_link_edit'), url(r'^setup/(?P<smart_link_pk>\d+)/edit/$', 'smart_link_edit', (), 'smart_link_edit'),
url(r'^setup/(?P<smart_link_pk>\d+)/condition/list/$', 'smart_link_condition_list', (), 'smart_link_condition_list'), url(r'^setup/(?P<smart_link_pk>\d+)/condition/list/$', 'smart_link_condition_list', (), 'smart_link_condition_list'),
url(r'^setup/(?P<smart_link_pk>\d+)/condition/create/$', 'smart_link_condition_create', (), 'smart_link_condition_create'), url(r'^setup/(?P<smart_link_pk>\d+)/condition/create/$', 'smart_link_condition_create', (), 'smart_link_condition_create'),
url(r'^setup/smart_link/condition/(?P<smart_link_condition_pk>\d+)/edit/$', 'smart_link_condition_edit', (), 'smart_link_condition_edit'), url(r'^setup/smart_link/condition/(?P<smart_link_condition_pk>\d+)/edit/$', 'smart_link_condition_edit', (), 'smart_link_condition_edit'),
+36 -36
View File
@@ -9,7 +9,7 @@ from django.shortcuts import get_object_or_404, render_to_response
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.template import RequestContext from django.template import RequestContext
from common.utils import generate_choices_w_labels, encapsulate from common.utils import encapsulate
from common.widgets import two_state_template from common.widgets import two_state_template
from documents.models import Document from documents.models import Document
from documents.views import document_list from documents.views import document_list
@@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
def smart_link_action(request): def smart_link_action(request):
#Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW]) #Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
action = request.GET.get('action', None) action = request.GET.get('action', None)
if not action: if not action:
@@ -45,12 +45,12 @@ def smart_link_action(request):
def smart_link_instance_view(request, document_id, smart_link_pk): def smart_link_instance_view(request, document_id, smart_link_pk):
document = get_object_or_404(Document, pk=document_id) document = get_object_or_404(Document, pk=document_id)
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk) smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_SMART_LINK_VIEW, request.user, smart_link) AccessEntry.objects.check_access(PERMISSION_SMART_LINK_VIEW, request.user, smart_link)
object_list, errors = SmartLink.objects.get_smart_link_instances_for(document, smart_link) object_list, errors = SmartLink.objects.get_smart_link_instances_for(document, smart_link)
return document_list( return document_list(
@@ -86,7 +86,7 @@ def smart_link_instances_for_document(request, document_id):
for key, value in smart_link_instances.items(): for key, value in smart_link_instances.items():
if key not in smart_link_instances_keys_filtered: if key not in smart_link_instances_keys_filtered:
smart_link_instances.pop(key) smart_link_instances.pop(key)
value['documents'] = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_VIEW, request.user, value['documents']) value['documents'] = AccessEntry.objects.filter_objects_by_access(PERMISSION_DOCUMENT_VIEW, request.user, value['documents'])
if smart_link_instances: if smart_link_instances:
@@ -116,30 +116,30 @@ def smart_link_instances_for_document(request, document_id):
'document': document, 'document': document,
'subtemplates_list': subtemplates_list, 'subtemplates_list': subtemplates_list,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_list(request): def smart_link_list(request):
qs = SmartLink.objects.all() qs = SmartLink.objects.all()
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_VIEW])
except PermissionDenied: except PermissionDenied:
qs = AccessEntry.objects.filter_objects_by_access(PERMISSION_SMART_LINK_VIEW, request.user, qs) qs = AccessEntry.objects.filter_objects_by_access(PERMISSION_SMART_LINK_VIEW, request.user, qs)
return render_to_response('generic_list.html', { return render_to_response('generic_list.html', {
'title': _(u'smart links'), 'title': _(u'smart links'),
'object_list': qs, 'object_list': qs,
'extra_columns': [ 'extra_columns': [
{'name': _(u'dynamic title'), 'attribute': 'dynamic_title'}, {'name': _(u'dynamic title'), 'attribute': 'dynamic_title'},
{'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))}, {'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))},
], ],
'hide_link': True, 'hide_link': True,
'list_object_variable_name': 'smart_link', 'list_object_variable_name': 'smart_link',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_create(request): def smart_link_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE])
@@ -155,9 +155,9 @@ def smart_link_create(request):
return render_to_response('generic_form.html', { return render_to_response('generic_form.html', {
'form': form, 'form': form,
'title': _(u'Create new smart link') 'title': _(u'Create new smart link')
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_edit(request, smart_link_pk): def smart_link_edit(request, smart_link_pk):
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk) smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
@@ -180,16 +180,16 @@ def smart_link_edit(request, smart_link_pk):
'object': smart_link, 'object': smart_link,
'form': form, 'form': form,
'title': _(u'Edit smart link: %s') % smart_link 'title': _(u'Edit smart link: %s') % smart_link
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_delete(request, smart_link_pk): def smart_link_delete(request, smart_link_pk):
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk) smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_DELETE]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_DELETE])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_SMART_LINK_DELETE, request.user, smart_link) AccessEntry.objects.check_access(PERMISSION_SMART_LINK_DELETE, request.user, smart_link)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
@@ -212,26 +212,26 @@ def smart_link_delete(request, smart_link_pk):
'next': next, 'next': next,
'previous': previous, 'previous': previous,
'form_icon': u'link_delete.png', 'form_icon': u'link_delete.png',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_condition_list(request, smart_link_pk): def smart_link_condition_list(request, smart_link_pk):
smart_link = get_object_or_404(SmartLink, pk=smart_link_pk) smart_link = get_object_or_404(SmartLink, pk=smart_link_pk)
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link) AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link)
return render_to_response('generic_list.html', { return render_to_response('generic_list.html', {
'title': _(u'conditions for smart link: %s') % smart_link, 'title': _(u'conditions for smart link: %s') % smart_link,
'object_list': smart_link.smartlinkcondition_set.all(), 'object_list': smart_link.smartlinkcondition_set.all(),
'extra_columns': [ 'extra_columns': [
{'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))}, {'name': _(u'enabled'), 'attribute': encapsulate(lambda x: two_state_template(x.enabled))},
], ],
'hide_link': True, 'hide_link': True,
'object': smart_link, 'object': smart_link,
'list_object_variable_name': 'condition', 'list_object_variable_name': 'condition',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
@@ -241,14 +241,14 @@ def smart_link_condition_create(request, smart_link_pk):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link) AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link)
if request.method == 'POST': if request.method == 'POST':
form = SmartLinkConditionForm(request.POST) form = SmartLinkConditionForm(request.POST)
if form.is_valid(): if form.is_valid():
new_smart_link_condition = form.save(commit=False) new_smart_link_condition = form.save(commit=False)
new_smart_link_condition.smart_link = smart_link new_smart_link_condition.smart_link = smart_link
new_smart_link_condition.save() new_smart_link_condition.save()
messages.success(request, _(u'Smart link condition: "%s" created successfully.') % new_smart_link_condition) messages.success(request, _(u'Smart link condition: "%s" created successfully.') % new_smart_link_condition)
return HttpResponseRedirect(reverse('smart_link_condition_list', args=[smart_link.pk])) return HttpResponseRedirect(reverse('smart_link_condition_list', args=[smart_link.pk]))
else: else:
@@ -257,8 +257,8 @@ def smart_link_condition_create(request, smart_link_pk):
return render_to_response('generic_form.html', { return render_to_response('generic_form.html', {
'form': form, 'form': form,
'title': _(u'Add new conditions to smart link: "%s"') % smart_link, 'title': _(u'Add new conditions to smart link: "%s"') % smart_link,
'object': smart_link, 'object': smart_link,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_condition_edit(request, smart_link_condition_pk): def smart_link_condition_edit(request, smart_link_condition_pk):
@@ -267,7 +267,7 @@ def smart_link_condition_edit(request, smart_link_condition_pk):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link_condition.smart_link) AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link_condition.smart_link)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
@@ -294,8 +294,8 @@ def smart_link_condition_edit(request, smart_link_condition_pk):
{'object': 'object', 'name': _(u'smart link')}, {'object': 'object', 'name': _(u'smart link')},
{'object': 'condition', 'name': _(u'condition')} {'object': 'condition', 'name': _(u'condition')}
], ],
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_condition_delete(request, smart_link_condition_pk): def smart_link_condition_delete(request, smart_link_condition_pk):
@@ -304,7 +304,7 @@ def smart_link_condition_delete(request, smart_link_condition_pk):
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link_condition.smart_link) AccessEntry.objects.check_accesses([PERMISSION_SMART_LINK_CREATE, PERMISSION_SMART_LINK_EDIT], request.user, smart_link_condition.smart_link)
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/'))) next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', '/')))
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/'))) previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', '/')))
@@ -332,7 +332,7 @@ def smart_link_condition_delete(request, smart_link_condition_pk):
'next': next, 'next': next,
'previous': previous, 'previous': previous,
'form_icon': u'cog_delete.png', 'form_icon': u'cog_delete.png',
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
def smart_link_acl_list(request, smart_link_pk): def smart_link_acl_list(request, smart_link_pk):
-1
View File
@@ -3,7 +3,6 @@ from __future__ import absolute_import
import logging import logging
import datetime import datetime
from django.db.utils import DatabaseError
from django.db.utils import IntegrityError from django.db.utils import IntegrityError
from django.db import transaction from django.db import transaction
from django.db import models from django.db import models
+1 -1
View File
@@ -21,7 +21,7 @@ class Lock(models.Model):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
self.creation_datetime = datetime.datetime.now() self.creation_datetime = datetime.datetime.now()
if not self.timeout and not kwarget.get('timeout'): if not self.timeout and not kwargs.get('timeout'):
self.timeout = DEFAULT_LOCK_TIMEOUT self.timeout = DEFAULT_LOCK_TIMEOUT
super(Lock, self).save(*args, **kwargs) super(Lock, self).save(*args, **kwargs)
+2 -2
View File
@@ -12,7 +12,7 @@ from .conf.settings import SIDE_BAR_SEARCH, DISABLE_HOME_VIEW
__author__ = 'Roberto Rosario' __author__ = 'Roberto Rosario'
__copyright__ = 'Copyright 2011 Roberto Rosario' __copyright__ = 'Copyright 2011 Roberto Rosario'
__credits__ = ['Roberto Rosario',] __credits__ = ['Roberto Rosario',]
__license__ = 'GPL' __license__ = 'GPL'
__maintainer__ = 'Roberto Rosario' __maintainer__ = 'Roberto Rosario'
__email__ = 'roberto.rosario.gonzalez@gmail.com' __email__ = 'roberto.rosario.gonzalez@gmail.com'
@@ -58,7 +58,7 @@ __version__ = get_version()
if 'django.contrib.admin' in settings.INSTALLED_APPS: if 'django.contrib.admin' in settings.INSTALLED_APPS:
register_setup(admin_site) register_setup(admin_site)
register_tool(maintenance_menu) register_tool(maintenance_menu)
register_tool(statistics) register_tool(statistics)
register_tool(diagnostics) register_tool(diagnostics)
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.contrib import admin from django.contrib import admin
+14 -14
View File
@@ -1,5 +1,5 @@
'''Metadata handling commonalities''' """Metadata handling commonalities"""
from __future__ import absolute_import from __future__ import absolute_import
from urllib import unquote_plus from urllib import unquote_plus
@@ -9,9 +9,9 @@ from .models import DocumentMetadata, MetadataType
def decode_metadata_from_url(url_dict): def decode_metadata_from_url(url_dict):
''' """
Parse a URL query string to a list of metadata Parse a URL query string to a list of metadata
''' """
metadata_dict = { metadata_dict = {
'id': {}, 'id': {},
'value': {} 'value': {}
@@ -35,19 +35,19 @@ def decode_metadata_from_url(url_dict):
def save_metadata_list(metadata_list, document, create=False): def save_metadata_list(metadata_list, document, create=False):
''' """
Take a list of metadata dictionaries and associate them to a Take a list of metadata dictionaries and associate them to a
document document
''' """
for item in metadata_list: for item in metadata_list:
save_metadata(item, document, create) save_metadata(item, document, create)
def save_metadata(metadata_dict, document, create=False): def save_metadata(metadata_dict, document, create=False):
''' """
Take a dictionary of metadata type & value and associate it to a Take a dictionary of metadata type & value and associate it to a
document document
''' """
if create: if create:
# Use matched metadata now to create document metadata # Use matched metadata now to create document metadata
document_metadata, created = DocumentMetadata.objects.get_or_create( document_metadata, created = DocumentMetadata.objects.get_or_create(
@@ -81,16 +81,16 @@ def save_metadata(metadata_dict, document, create=False):
def metadata_repr(metadata_list): def metadata_repr(metadata_list):
''' """
Return a printable representation of a metadata list Return a printable representation of a metadata list
''' """
return u', '.join(metadata_repr_as_list(metadata_list)) return u', '.join(metadata_repr_as_list(metadata_list))
def metadata_repr_as_list(metadata_list): def metadata_repr_as_list(metadata_list):
''' """
Turn a list of metadata into a list of printable representations Turn a list of metadata into a list of printable representations
''' """
output = [] output = []
for metadata_dict in metadata_list: for metadata_dict in metadata_list:
try: try:
@@ -103,7 +103,7 @@ def metadata_repr_as_list(metadata_list):
def get_metadata_string(document): def get_metadata_string(document):
''' """
Return a formated representation of a document's metadata values Return a formated representation of a document's metadata values
''' """
return u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in DocumentMetadata.objects.filter(document=document).select_related('metadata_type')]) return u', '.join([u'%s - %s' % (metadata.metadata_type, metadata.value) for metadata in DocumentMetadata.objects.filter(document=document).select_related('metadata_type')])
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django import forms from django import forms
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
+11 -11
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@@ -12,9 +12,9 @@ available_functions_string = (_(u' Available functions: %s') % u','.join([u'%s()
class MetadataType(models.Model): class MetadataType(models.Model):
''' """
Define a type of metadata Define a type of metadata
''' """
name = models.CharField(unique=True, max_length=48, verbose_name=_(u'name'), help_text=_(u'Do not use python reserved words, or spaces.')) name = models.CharField(unique=True, max_length=48, verbose_name=_(u'name'), help_text=_(u'Do not use python reserved words, or spaces.'))
title = models.CharField(max_length=48, verbose_name=_(u'title'), blank=True, null=True) title = models.CharField(max_length=48, verbose_name=_(u'title'), blank=True, null=True)
default = models.CharField(max_length=128, blank=True, null=True, default = models.CharField(max_length=128, blank=True, null=True,
@@ -35,9 +35,9 @@ class MetadataType(models.Model):
class MetadataSet(models.Model): class MetadataSet(models.Model):
''' """
Define a group of metadata types Define a group of metadata types
''' """
title = models.CharField(max_length=48, verbose_name=_(u'title')) title = models.CharField(max_length=48, verbose_name=_(u'title'))
def __unicode__(self): def __unicode__(self):
@@ -50,10 +50,10 @@ class MetadataSet(models.Model):
class MetadataSetItem(models.Model): class MetadataSetItem(models.Model):
''' """
Define the set of metadata that relates to a set or group of Define the set of metadata that relates to a set or group of
metadata fields metadata fields
''' """
metadata_set = models.ForeignKey(MetadataSet, verbose_name=_(u'metadata set')) metadata_set = models.ForeignKey(MetadataSet, verbose_name=_(u'metadata set'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type')) metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'metadata type'))
#required = models.BooleanField(default=True, verbose_name=_(u'required')) #required = models.BooleanField(default=True, verbose_name=_(u'required'))
@@ -67,10 +67,10 @@ class MetadataSetItem(models.Model):
class DocumentMetadata(models.Model): class DocumentMetadata(models.Model):
''' """
Link a document to a specific instance of a metadata type with it's Link a document to a specific instance of a metadata type with it's
current value current value
''' """
document = models.ForeignKey(Document, verbose_name=_(u'document')) document = models.ForeignKey(Document, verbose_name=_(u'document'))
metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'type')) metadata_type = models.ForeignKey(MetadataType, verbose_name=_(u'type'))
value = models.CharField(max_length=256, blank=True, verbose_name=_(u'value'), db_index=True) value = models.CharField(max_length=256, blank=True, verbose_name=_(u'value'), db_index=True)
@@ -84,10 +84,10 @@ class DocumentMetadata(models.Model):
class DocumentTypeDefaults(models.Model): class DocumentTypeDefaults(models.Model):
''' """
Default preselected metadata types and metadata set per document Default preselected metadata types and metadata set per document
type type
''' """
document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type')) document_type = models.ForeignKey(DocumentType, verbose_name=_(u'document type'))
default_metadata_sets = models.ManyToManyField(MetadataSet, blank=True, verbose_name=_(u'default metadata sets')) default_metadata_sets = models.ManyToManyField(MetadataSet, blank=True, verbose_name=_(u'default metadata sets'))
default_metadata = models.ManyToManyField(MetadataType, blank=True, verbose_name=_(u'default metadata')) default_metadata = models.ManyToManyField(MetadataType, blank=True, verbose_name=_(u'default metadata'))
+1 -1
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+18 -18
View File
@@ -1,4 +1,4 @@
from __future__ import absolute_import from __future__ import absolute_import
from django.shortcuts import render_to_response from django.shortcuts import render_to_response
from django.template import RequestContext from django.template import RequestContext
@@ -46,10 +46,10 @@ def metadata_edit(request, document_id=None, document_id_list=None):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_EDIT])
except PermissionDenied: except PermissionDenied:
documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_EDIT, request.user, documents) documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_EDIT, request.user, documents)
if not documents: if not documents:
messages.error(request, _(u'Must provide at least one document.')) messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
post_action_redirect = reverse('document_list_recent') post_action_redirect = reverse('document_list_recent')
@@ -141,7 +141,7 @@ def metadata_add(request, document_id=None, document_id_list=None):
if not documents: if not documents:
messages.error(request, _(u'Must provide at least one document.')) messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
for document in documents: for document in documents:
RecentDocument.objects.add_document_for_user(request.user, document) RecentDocument.objects.add_document_for_user(request.user, document)
@@ -205,12 +205,12 @@ def metadata_remove(request, document_id=None, document_id_list=None):
elif document_id_list: elif document_id_list:
documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')] documents = [get_object_or_404(Document, pk=document_id) for document_id in document_id_list.split(',')]
try: try:
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_REMOVE]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_DOCUMENT_REMOVE])
except PermissionDenied: except PermissionDenied:
documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_REMOVE, request.user, documents) documents = AccessEntry.objects.filter_objects_by_access(PERMISSION_METADATA_DOCUMENT_REMOVE, request.user, documents)
if not documents: if not documents:
messages.error(request, _(u'Must provide at least one document.')) messages.error(request, _(u'Must provide at least one document.'))
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
@@ -304,7 +304,7 @@ def metadata_view(request, document_id):
'hide_link': True, 'hide_link': True,
'object': document, 'object': document,
}, context_instance=RequestContext(request)) }, context_instance=RequestContext(request))
# Setup views # Setup views
def setup_metadata_type_list(request): def setup_metadata_type_list(request):
@@ -323,12 +323,12 @@ def setup_metadata_type_list(request):
} }
return render_to_response('generic_list.html', context, return render_to_response('generic_list.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def setup_metadata_type_edit(request, metadatatype_id): def setup_metadata_type_edit(request, metadatatype_id):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_EDIT]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_EDIT])
metadata_type = get_object_or_404(MetadataType, pk=metadatatype_id) metadata_type = get_object_or_404(MetadataType, pk=metadatatype_id)
if request.method == 'POST': if request.method == 'POST':
@@ -351,12 +351,12 @@ def setup_metadata_type_edit(request, metadatatype_id):
'object': metadata_type, 'object': metadata_type,
'object_name': _(u'metadata type'), 'object_name': _(u'metadata type'),
}, },
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def setup_metadata_type_create(request): def setup_metadata_type_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_CREATE]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_CREATE])
if request.method == 'POST': if request.method == 'POST':
form = MetadataTypeForm(request.POST) form = MetadataTypeForm(request.POST)
if form.is_valid(): if form.is_valid():
@@ -375,7 +375,7 @@ def setup_metadata_type_create(request):
def setup_metadata_type_delete(request, metadatatype_id): def setup_metadata_type_delete(request, metadatatype_id):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_DELETE]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_TYPE_DELETE])
metadata_type = get_object_or_404(MetadataType, pk=metadatatype_id) metadata_type = get_object_or_404(MetadataType, pk=metadatatype_id)
post_action_redirect = reverse('setup_metadata_type_list') post_action_redirect = reverse('setup_metadata_type_list')
@@ -423,7 +423,7 @@ def setup_metadata_set_list(request):
} }
return render_to_response('generic_list.html', context, return render_to_response('generic_list.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def get_set_members(metadata_set): def get_set_members(metadata_set):
@@ -471,7 +471,7 @@ def setup_metadata_set_edit(request, metadata_set_id):
def setup_metadata_set_create(request): def setup_metadata_set_create(request):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_SET_CREATE]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_SET_CREATE])
if request.method == 'POST': if request.method == 'POST':
form = MetadataSetForm(request.POST) form = MetadataSetForm(request.POST)
if form.is_valid(): if form.is_valid():
@@ -490,7 +490,7 @@ def setup_metadata_set_create(request):
def setup_metadata_set_delete(request, metadata_set_id): def setup_metadata_set_delete(request, metadata_set_id):
Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_SET_DELETE]) Permission.objects.check_permissions(request.user, [PERMISSION_METADATA_SET_DELETE])
metadata_set = get_object_or_404(MetadataSet, pk=metadata_set_id) metadata_set = get_object_or_404(MetadataSet, pk=metadata_set_id)
post_action_redirect = reverse('setup_metadata_set_list') post_action_redirect = reverse('setup_metadata_set_list')
@@ -566,7 +566,7 @@ def setup_document_type_metadata(request, document_type_id):
# Initialize defaults # Initialize defaults
DocumentTypeDefaults.objects.get_or_create(document_type=document_type) DocumentTypeDefaults.objects.get_or_create(document_type=document_type)
return assign_remove( return assign_remove(
request, request,
left_list=lambda: generate_choices_w_labels(get_document_type_metadata_non_members(document_type)), left_list=lambda: generate_choices_w_labels(get_document_type_metadata_non_members(document_type)),
+1 -3
View File
@@ -1,5 +1,3 @@
import copy
object_navigation = {} object_navigation = {}
multi_object_navigation = {} multi_object_navigation = {}
model_list_columns = {} model_list_columns = {}
@@ -46,7 +44,7 @@ def register_links(src, links, menu_name=None, position=None):
object_navigation[menu_name][src]['links'].extend(links) object_navigation[menu_name][src]['links'].extend(links)
def register_top_menu(name, link, children_views=None, def register_top_menu(name, link, children_views=None,
children_path_regex=None, children_view_regex=None, children_path_regex=None, children_view_regex=None,
position=None): position=None):
""" """
+6 -7
View File
@@ -8,13 +8,11 @@ from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.template.defaultfilters import capfirst from django.template.defaultfilters import capfirst
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.template import RequestContext from django.template import RequestContext, Variable
from django.template import (TemplateSyntaxError, Library,
VariableDoesNotExist, Node, Variable)
from permissions.models import Permission from permissions.models import Permission
from .templatetags.navigation_tags import resolve_links, _get_object_navigation_links from .templatetags.navigation_tags import resolve_links
from .utils import resolve_to_name from .utils import resolve_to_name
@@ -27,7 +25,8 @@ def button_navigation_widget(request, link):
return u'' return u''
else: else:
return render_widget(request, link) return render_widget(request, link)
def render_widget(request, link): def render_widget(request, link):
context = RequestContext(request) context = RequestContext(request)
@@ -37,7 +36,7 @@ def render_widget(request, link):
query_string = urlparse.urlparse(request.get_full_path()).query or urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).query query_string = urlparse.urlparse(request.get_full_path()).query or urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).query
parsed_query_string = urlparse.parse_qs(query_string) parsed_query_string = urlparse.parse_qs(query_string)
links = resolve_links(context, [link], current_view, current_path, parsed_query_string) links = resolve_links(context, [link], current_view, current_path, parsed_query_string)
if links: if links:
link = links[0] link = links[0]
+10 -7
View File
@@ -1,15 +1,14 @@
from __future__ import absolute_import from __future__ import absolute_import
import logging import logging
from django.db import transaction from django.db import transaction
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext from django.utils.translation import ugettext
from django.db.models.signals import post_save from django.db.models.signals import post_save
from django.dispatch import receiver from django.dispatch import receiver
from navigation.api import register_links, register_top_menu, register_multi_item_links from navigation.api import register_links, register_multi_item_links
from permissions.models import Permission, PermissionNamespace
from documents.models import Document, DocumentVersion from documents.models import Document, DocumentVersion
from main.api import register_maintenance_links from main.api import register_maintenance_links
from project_tools.api import register_tool from project_tools.api import register_tool
@@ -18,11 +17,12 @@ from acls.api import class_permissions
from scheduler.api import register_interval_job from scheduler.api import register_interval_job
from .conf.settings import (AUTOMATIC_OCR, QUEUE_PROCESSING_INTERVAL) from .conf.settings import (AUTOMATIC_OCR, QUEUE_PROCESSING_INTERVAL)
from .models import DocumentQueue, QueueTransformation, QueueDocument from .models import DocumentQueue, QueueTransformation
from .tasks import task_process_document_queues from .tasks import task_process_document_queues
from .permissions import (PERMISSION_OCR_DOCUMENT, from .permissions import (PERMISSION_OCR_DOCUMENT,
PERMISSION_OCR_DOCUMENT_DELETE, PERMISSION_OCR_QUEUE_ENABLE_DISABLE, PERMISSION_OCR_DOCUMENT_DELETE, PERMISSION_OCR_QUEUE_ENABLE_DISABLE,
PERMISSION_OCR_CLEAN_ALL_PAGES, PERMISSION_OCR_QUEUE_EDIT) PERMISSION_OCR_CLEAN_ALL_PAGES)
from .exceptions import AlreadyQueued
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -77,7 +77,10 @@ def document_post_save(sender, instance, **kwargs):
logger.debug('instance: %s' % instance) logger.debug('instance: %s' % instance)
if kwargs.get('created', False): if kwargs.get('created', False):
if AUTOMATIC_OCR: if AUTOMATIC_OCR:
DocumentQueue.objects.queue_document(instance.document) try:
DocumentQueue.objects.queue_document(instance.document)
except AlreadyQueued:
pass
# Disabled because it appears Django execute signals using the same # Disabled because it appears Django execute signals using the same
@@ -85,7 +88,7 @@ def document_post_save(sender, instance, **kwargs):
# the OCR process completes which could take several minutes :/ # the OCR process completes which could take several minutes :/
#@receiver(post_save, dispatch_uid='call_queue', sender=QueueDocument) #@receiver(post_save, dispatch_uid='call_queue', sender=QueueDocument)
#def call_queue(sender, **kwargs): #def call_queue(sender, **kwargs):
# if kwargs.get('created', False): # if kwargs.get('created', False):
# logger.debug('got call_queue signal: %s' % kwargs) # logger.debug('got call_queue signal: %s' % kwargs)
# task_process_document_queues() # task_process_document_queues()
-1
View File
@@ -14,7 +14,6 @@ register_settings(
{'name': u'NODE_CONCURRENT_EXECUTION', 'global_name': u'OCR_NODE_CONCURRENT_EXECUTION', 'default': 1, 'description': _(u'Maximum amount of concurrent document OCRs a node can perform.')}, {'name': u'NODE_CONCURRENT_EXECUTION', 'global_name': u'OCR_NODE_CONCURRENT_EXECUTION', 'default': 1, 'description': _(u'Maximum amount of concurrent document OCRs a node can perform.')},
{'name': u'AUTOMATIC_OCR', 'global_name': u'OCR_AUTOMATIC_OCR', 'default': False, 'description': _(u'Automatically queue newly created documents for OCR.')}, {'name': u'AUTOMATIC_OCR', 'global_name': u'OCR_AUTOMATIC_OCR', 'default': False, 'description': _(u'Automatically queue newly created documents for OCR.')},
{'name': u'QUEUE_PROCESSING_INTERVAL', 'global_name': u'OCR_QUEUE_PROCESSING_INTERVAL', 'default': 10}, {'name': u'QUEUE_PROCESSING_INTERVAL', 'global_name': u'OCR_QUEUE_PROCESSING_INTERVAL', 'default': 10},
{'name': u'CACHE_URI', 'global_name': u'OCR_CACHE_URI', 'default': None, 'description': _(u'URI in the form: "memcached://127.0.0.1:11211/" to specify a cache backend to use for locking. Multiple hosts can be specified separated by a semicolon.')},
{'name': u'UNPAPER_PATH', 'global_name': u'OCR_UNPAPER_PATH', 'default': u'/usr/bin/unpaper', 'description': _(u'File path to unpaper program.'), 'exists': True}, {'name': u'UNPAPER_PATH', 'global_name': u'OCR_UNPAPER_PATH', 'default': u'/usr/bin/unpaper', 'description': _(u'File path to unpaper program.'), 'exists': True},
] ]
) )
+6 -6
View File
@@ -1,21 +1,21 @@
class AlreadyQueued(Exception): class AlreadyQueued(Exception):
''' """
Raised when a trying to queue document already in the queue Raised when a trying to queue document already in the queue
''' """
pass pass
class TesseractError(Exception): class TesseractError(Exception):
''' """
Raised by tesseract Raised by tesseract
''' """
pass pass
class UnpaperError(Exception): class UnpaperError(Exception):
''' """
Raised by unpaper Raised by unpaper
''' """
pass pass
+4 -5
View File
@@ -3,10 +3,9 @@ import logging
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from converter import office_converter
from converter import office_converter from converter import office_converter
from converter.office_converter import OfficeConverter from converter.office_converter import OfficeConverter
from converter.exceptions import OfficeBackendError, OfficeConversionError from converter.exceptions import OfficeConversionError
from documents.utils import document_save_to_temp_dir from documents.utils import document_save_to_temp_dir
from ocr.parsers.exceptions import ParserError, ParserUnknownFile from ocr.parsers.exceptions import ParserError, ParserUnknownFile
@@ -27,7 +26,7 @@ def register_parser(function, mimetype=None, mimetypes=None):
def pdf_parser(document_page, descriptor=None): def pdf_parser(document_page, descriptor=None):
if not descriptor: if not descriptor:
descriptor = document_page.document_version.open() descriptor = document_page.document_version.open()
pdf_pages = slate.PDF(descriptor) pdf_pages = slate.PDF(descriptor)
descriptor.close() descriptor.close()
@@ -45,7 +44,7 @@ def office_parser(document_page):
office_converter = OfficeConverter() office_converter = OfficeConverter()
document_file = document_save_to_temp_dir(document_page.document, document_page.document.checksum) document_file = document_save_to_temp_dir(document_page.document, document_page.document.checksum)
logger.debug('document_file: %s', document_file) logger.debug('document_file: %s', document_file)
office_converter.convert(document_file, mimetype=document_page.document.file_mimetype) office_converter.convert(document_file, mimetype=document_page.document.file_mimetype)
if office_converter.exists: if office_converter.exists:
input_filepath = office_converter.output_filepath input_filepath = office_converter.output_filepath
@@ -58,7 +57,7 @@ def office_parser(document_page):
except OfficeConversionError, msg: except OfficeConversionError, msg:
print msg print msg
raise ParserError raise ParserError
def parse_document_page(document_page): def parse_document_page(document_page):
logger.debug('executing') logger.debug('executing')
+4 -34
View File
@@ -2,8 +2,6 @@ from __future__ import absolute_import
from datetime import timedelta, datetime from datetime import timedelta, datetime
import platform import platform
from time import sleep
from random import random
import logging import logging
from django.db.models import Q from django.db.models import Q
@@ -17,7 +15,7 @@ from .literals import (QUEUEDOCUMENT_STATE_PENDING,
QUEUEDOCUMENT_STATE_ERROR) QUEUEDOCUMENT_STATE_ERROR)
from .models import QueueDocument, DocumentQueue from .models import QueueDocument, DocumentQueue
from .conf.settings import (NODE_CONCURRENT_EXECUTION, REPLICATION_DELAY, from .conf.settings import (NODE_CONCURRENT_EXECUTION, REPLICATION_DELAY,
CACHE_URI, QUEUE_PROCESSING_INTERVAL) QUEUE_PROCESSING_INTERVAL)
LOCK_EXPIRE = 60 * 10 # Lock expires in 10 minutes LOCK_EXPIRE = 60 * 10 # Lock expires in 10 minutes
# TODO: Tie LOCK_EXPIRATION with hard task timeout # TODO: Tie LOCK_EXPIRATION with hard task timeout
@@ -42,44 +40,16 @@ def task_process_queue_document(queue_document_id):
queue_document.state = QUEUEDOCUMENT_STATE_ERROR queue_document.state = QUEUEDOCUMENT_STATE_ERROR
queue_document.result = e queue_document.result = e
queue_document.save() queue_document.save()
lock.release() lock.release()
except LockError: except LockError:
logger.debug('unable to obtain lock') logger.debug('unable to obtain lock')
pass pass
def reset_orphans():
pass
'''
i = inspect().active()
active_tasks = []
orphans = []
if i:
for host, instances in i.items():
for instance in instances:
active_tasks.append(instance['id'])
for document_queue in DocumentQueue.objects.filter(state=DOCUMENTQUEUE_STATE_ACTIVE):
orphans = document_queue.queuedocument_set.\
filter(state=QUEUEDOCUMENT_STATE_PROCESSING).\
exclude(result__in=active_tasks)
for orphan in orphans:
orphan.result = _(u'Orphaned')
orphan.state = QUEUEDOCUMENT_STATE_PENDING
orphan.delay = False
orphan.node_name = None
orphan.save()
'''
def task_process_document_queues(): def task_process_document_queues():
logger.debug('executed') logger.debug('executed')
# reset_orphans() # TODO: reset_orphans()
# Causes problems with big clusters increased latency
# Disabled until better solution
q_pending = Q(state=QUEUEDOCUMENT_STATE_PENDING) q_pending = Q(state=QUEUEDOCUMENT_STATE_PENDING)
q_delayed = Q(delay=True) q_delayed = Q(delay=True)
q_delay_interval = Q(datetime_submitted__lt=datetime.now() - timedelta(seconds=REPLICATION_DELAY)) q_delay_interval = Q(datetime_submitted__lt=datetime.now() - timedelta(seconds=REPLICATION_DELAY))
@@ -100,7 +70,7 @@ def task_process_document_queues():
#print 'DocumentQueueWatcher exception: %s' % e #print 'DocumentQueueWatcher exception: %s' % e
finally: finally:
# Don't process anymore from this queryset, might be stale # Don't process anymore from this queryset, might be stale
break; break
else: else:
logger.debug('already processing maximun') logger.debug('already processing maximun')
else: else:
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+3 -3
View File
@@ -123,9 +123,9 @@ def queue_document_multiple_delete(request):
def submit_document_multiple(request): def submit_document_multiple(request):
for item_id in request.GET.get('id_list', '').split(','): for item_id in request.GET.get('id_list', '').split(','):
submit_document(request, item_id) submit_document(request, item_id)
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/')) return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))
def submit_document(request, document_id): def submit_document(request, document_id):
document = get_object_or_404(Document, pk=document_id) document = get_object_or_404(Document, pk=document_id)
@@ -134,7 +134,7 @@ def submit_document(request, document_id):
Permission.objects.check_permissions(request.user, [PERMISSION_OCR_DOCUMENT]) Permission.objects.check_permissions(request.user, [PERMISSION_OCR_DOCUMENT])
except PermissionDenied: except PermissionDenied:
AccessEntry.objects.check_access(PERMISSION_OCR_DOCUMENT, request.user, document) AccessEntry.objects.check_access(PERMISSION_OCR_DOCUMENT, request.user, document)
return submit_document_to_queue(request, document=document, return submit_document_to_queue(request, document=document,
post_submit_redirect=request.META.get('HTTP_REFERER', '/')) post_submit_redirect=request.META.get('HTTP_REFERER', '/'))
-1
View File
@@ -1 +0,0 @@
+37 -37
View File
@@ -13,7 +13,7 @@ from django.core.exceptions import PermissionDenied
from common.models import AnonymousUserSingleton from common.models import AnonymousUserSingleton
from .managers import (RoleMemberManager, StoredPermissionManager) from .managers import (RoleMemberManager, StoredPermissionManager)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -21,7 +21,7 @@ class PermissionNamespace(object):
def __init__(self, name, label): def __init__(self, name, label):
self.name = name self.name = name
self.label = label self.label = label
def __unicode__(self): def __unicode__(self):
return unicode(self.label) return unicode(self.label)
@@ -29,17 +29,17 @@ class PermissionNamespace(object):
class PermissionDoesNotExists(Exception): class PermissionDoesNotExists(Exception):
pass pass
class PermissionManager(object): class PermissionManager(object):
_permissions = {} _permissions = {}
DoesNotExist = PermissionDoesNotExists() DoesNotExist = PermissionDoesNotExists()
@classmethod @classmethod
def register(cls, namespace, name, label): def register(cls, namespace, name, label):
permission = Permission(namespace, name, label) permission = Permission(namespace, name, label)
cls._permissions[permission.uuid] = permission cls._permissions[permission.uuid] = permission
return permission return permission
@classmethod @classmethod
def check_permissions(cls, requester, permission_list): def check_permissions(cls, requester, permission_list):
for permission in permission_list: for permission in permission_list:
@@ -49,11 +49,11 @@ class PermissionManager(object):
logger.debug('no permission') logger.debug('no permission')
raise PermissionDenied(ugettext(u'Insufficient permissions.')) raise PermissionDenied(ugettext(u'Insufficient permissions.'))
@classmethod @classmethod
def get_for_holder(cls, holder): def get_for_holder(cls, holder):
return StoredPermission.objects.get_for_holder(holder) return StoredPermission.objects.get_for_holder(holder)
@classmethod @classmethod
def all(cls): def all(cls):
# Return sorted permisions by namespace.name # Return sorted permisions by namespace.name
@@ -69,21 +69,21 @@ class PermissionManager(object):
return cls._permissions[get_dict['pk']].get_stored_permission() return cls._permissions[get_dict['pk']].get_stored_permission()
except KeyError: except KeyError:
raise Permission.DoesNotExist raise Permission.DoesNotExist
def __init__(self, model): def __init__(self, model):
self.model = model self.model = model
class Permission(object): class Permission(object):
DoesNotExist = PermissionDoesNotExists DoesNotExist = PermissionDoesNotExists
def __init__(self, namespace, name, label): def __init__(self, namespace, name, label):
self.namespace = namespace self.namespace = namespace
self.name = name self.name = name
self.label = label self.label = label
self.pk = self.uuid self.pk = self.uuid
def __unicode__(self): def __unicode__(self):
return unicode(self.label) return unicode(self.label)
@@ -93,7 +93,7 @@ class Permission(object):
@property @property
def uuid(self): def uuid(self):
return u'%s.%s' % (self.namespace.name, self.name) return u'%s.%s' % (self.namespace.name, self.name)
@property @property
def stored_permission(self): def stored_permission(self):
return self.get_stored_permission() return self.get_stored_permission()
@@ -107,17 +107,17 @@ class Permission(object):
stored_permission.save() stored_permission.save()
stored_permission.volatile_permission = self stored_permission.volatile_permission = self
return stored_permission return stored_permission
def requester_has_this(self, requester): def requester_has_this(self, requester):
stored_permission = self.get_stored_permission() stored_permission = self.get_stored_permission()
return stored_permission.requester_has_this(requester) return stored_permission.requester_has_this(requester)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
return self.get_stored_permission() return self.get_stored_permission()
Permission.objects = PermissionManager(Permission) Permission.objects = PermissionManager(Permission)
Permission._default_manager = Permission.objects Permission._default_manager = Permission.objects
class StoredPermission(models.Model): class StoredPermission(models.Model):
namespace = models.CharField(max_length=64, verbose_name=_(u'namespace')) namespace = models.CharField(max_length=64, verbose_name=_(u'namespace'))
@@ -126,62 +126,62 @@ class StoredPermission(models.Model):
objects = StoredPermissionManager() objects = StoredPermissionManager()
class Meta: class Meta:
ordering = ('namespace', ) ordering = ('namespace', )
unique_together = ('namespace', 'name') unique_together = ('namespace', 'name')
verbose_name = _(u'permission') verbose_name = _(u'permission')
verbose_name_plural = _(u'permissions') verbose_name_plural = _(u'permissions')
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(StoredPermission, self).__init__(*args, **kwargs) super(StoredPermission, self).__init__(*args, **kwargs)
self.volatile_permission = Permission.objects.get({'pk': '%s.%s' % (self.namespace, self.name)}, proxy_only=True) self.volatile_permission = Permission.objects.get({'pk': '%s.%s' % (self.namespace, self.name)}, proxy_only=True)
def __unicode__(self): def __unicode__(self):
return unicode(getattr(self, 'volatile_permission', self.name)) return unicode(getattr(self, 'volatile_permission', self.name))
def get_holders(self): def get_holders(self):
return [holder.holder_object for holder in self.permissionholder_set.all()] return [holder.holder_object for holder in self.permissionholder_set.all()]
def requester_has_this(self, requester): def requester_has_this(self, actor):
requester = AnonymousUserSingleton.objects.passthru_check(requester) actor = AnonymousUserSingleton.objects.passthru_check(actor)
logger.debug('requester: %s' % requester) logger.debug('actor: %s' % actor)
if isinstance(requester, User): if isinstance(actor, User):
if requester.is_superuser or requester.is_staff: if actor.is_superuser or actor.is_staff:
return True return True
# Request is one of the permission's holders? # Request is one of the permission's holders?
if requester in self.get_holders(): if actor in self.get_holders():
return True return True
# If not check if the requesters memberships objects is one of # If not check if the requesters memberships objects is one of
# the permission's holder? # the permission's holder?
roles = RoleMember.objects.get_roles_for_member(requester) roles = RoleMember.objects.get_roles_for_member(actor)
if isinstance(requester, User): if isinstance(actor, User):
groups = requester.groups.all() groups = actor.groups.all()
else: else:
groups = [] groups = []
for membership in list(set(roles) | set(groups)): for membership in list(set(roles) | set(groups)):
if self.requester_has_this(membership): if self.requester_has_this(membership):
return True return True
logger.debug('Fallthru') logger.debug('Fallthru')
return False return False
def grant_to(self, requester): def grant_to(self, actor):
requester = AnonymousUserSingleton.objects.passthru_check(requester) actor = AnonymousUserSingleton.objects.passthru_check(actor)
permission_holder, created = PermissionHolder.objects.get_or_create(permission=self, holder_type=ContentType.objects.get_for_model(requester), holder_id=requester.pk) permission_holder, created = PermissionHolder.objects.get_or_create(permission=self, holder_type=ContentType.objects.get_for_model(actor), holder_id=actor.pk)
return created return created
def revoke_from(self, holder): def revoke_from(self, actor):
requester = AnonymousUserSingleton.objects.passthru_check(requester) actor = AnonymousUserSingleton.objects.passthru_check(actor)
try: try:
permission_holder = PermissionHolder.objects.get(permission=self, holder_type=ContentType.objects.get_for_model(holder), holder_id=holder.pk) permission_holder = PermissionHolder.objects.get(permission=self, holder_type=ContentType.objects.get_for_model(actor), holder_id=actor.pk)
permission_holder.delete() permission_holder.delete()
return True return True
except PermissionHolder.DoesNotExist: except PermissionHolder.DoesNotExist:
return False return False
class PermissionHolder(models.Model): class PermissionHolder(models.Model):
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission')) permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
@@ -228,7 +228,7 @@ class Role(models.Model):
member = AnonymousUserSingleton.objects.passthru_check(member) member = AnonymousUserSingleton.objects.passthru_check(member)
member_type=ContentType.objects.get_for_model(member) member_type=ContentType.objects.get_for_model(member)
role_member = RoleMember.objects.get(role=self, member_type=member_type, member_id=member.pk) role_member = RoleMember.objects.get(role=self, member_type=member_type, member_id=member.pk)
role_member.delete() role_member.delete()
def members(self, filter_dict=None): def members(self, filter_dict=None):
filter_dict = filter_dict or {} filter_dict = filter_dict or {}
-1
View File
@@ -1 +0,0 @@
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}
+1 -1
View File
@@ -7,7 +7,7 @@ urlpatterns = patterns('permissions.views',
url(r'^role/(?P<role_id>\d+)/edit/$', 'role_edit', (), 'role_edit'), url(r'^role/(?P<role_id>\d+)/edit/$', 'role_edit', (), 'role_edit'),
url(r'^role/(?P<role_id>\d+)/delete/$', 'role_delete', (), 'role_delete'), url(r'^role/(?P<role_id>\d+)/delete/$', 'role_delete', (), 'role_delete'),
url(r'^role/(?P<role_id>\d+)/members/$', 'role_members', (), 'role_members'), url(r'^role/(?P<role_id>\d+)/members/$', 'role_members', (), 'role_members'),
url(r'^permissions/multiple/grant/$', 'permission_grant', (), 'permission_multiple_grant'), url(r'^permissions/multiple/grant/$', 'permission_grant', (), 'permission_multiple_grant'),
url(r'^permissions/multiple/revoke/$', 'permission_revoke', (), 'permission_multiple_revoke'), url(r'^permissions/multiple/revoke/$', 'permission_revoke', (), 'permission_multiple_revoke'),
) )
+21 -21
View File
@@ -24,7 +24,7 @@ from .models import Role, Permission, PermissionHolder, RoleMember
from .forms import RoleForm, RoleForm_view from .forms import RoleForm, RoleForm_view
from .permissions import (PERMISSION_ROLE_VIEW, PERMISSION_ROLE_EDIT, from .permissions import (PERMISSION_ROLE_VIEW, PERMISSION_ROLE_EDIT,
PERMISSION_ROLE_CREATE, PERMISSION_ROLE_DELETE, PERMISSION_ROLE_CREATE, PERMISSION_ROLE_DELETE,
PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE) PERMISSION_PERMISSION_GRANT, PERMISSION_PERMISSION_REVOKE)
from .widgets import role_permission_link from .widgets import role_permission_link
@@ -133,20 +133,20 @@ def permission_grant(request):
permission = Permission.objects.get({'pk': item_properties['permission_id']}) permission = Permission.objects.get({'pk': item_properties['permission_id']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
ct = get_object_or_404(ContentType, app_label=item_properties['requester_app_label'], model=item_properties['requester_model']) ct = get_object_or_404(ContentType, app_label=item_properties['requester_app_label'], model=item_properties['requester_model'])
requester_model = ct.model_class() requester_model = ct.model_class()
requester = get_object_or_404(requester_model, pk=item_properties['requester_id']) requester = get_object_or_404(requester_model, pk=item_properties['requester_id'])
items.append({'requester': requester, 'permission': permission}) items.append({'requester': requester, 'permission': permission})
sorted_items = sorted(items, key=operator.itemgetter('requester')) sorted_items = sorted(items, key=operator.itemgetter('requester'))
# Group items by requester # Group items by requester
groups = itertools.groupby(sorted_items, key=operator.itemgetter('requester')) groups = itertools.groupby(sorted_items, key=operator.itemgetter('requester'))
grouped_items = [(grouper, [permission['permission'] for permission in group_data]) for grouper, group_data in groups] grouped_items = [(grouper, [permission['permission'] for permission in group_data]) for grouper, group_data in groups]
# Warning: trial and error black magic ahead # Warning: trial and error black magic ahead
title_suffix = _(u' and ').join([_(u'%(permissions)s to %(requester)s') % {'permissions': ', '.join(['"%s"' % unicode(ps) for ps in p]), 'requester': unicode(r)} for r, p in grouped_items]) title_suffix = _(u' and ').join([_(u'%(permissions)s to %(requester)s') % {'permissions': ', '.join(['"%s"' % unicode(ps) for ps in p]), 'requester': unicode(r)} for r, p in grouped_items])
if len(grouped_items) == 1 and len(grouped_items[0][1]) == 1: if len(grouped_items) == 1 and len(grouped_items[0][1]) == 1:
permissions_label = _(u'permission') permissions_label = _(u'permission')
else: else:
@@ -174,13 +174,13 @@ def permission_grant(request):
'permissions_label': permissions_label, 'permissions_label': permissions_label,
'title_suffix': title_suffix, 'title_suffix': title_suffix,
} }
if len(grouped_items) == 1: if len(grouped_items) == 1:
context['object'] = grouped_items[0][0] context['object'] = grouped_items[0][0]
return render_to_response('generic_confirm.html', context, return render_to_response('generic_confirm.html', context,
context_instance=RequestContext(request)) context_instance=RequestContext(request))
def permission_revoke(request): def permission_revoke(request):
Permission.objects.check_permissions(request.user, [PERMISSION_PERMISSION_REVOKE]) Permission.objects.check_permissions(request.user, [PERMISSION_PERMISSION_REVOKE])
@@ -197,20 +197,20 @@ def permission_revoke(request):
permission = Permission.objects.get({'pk': item_properties['permission_id']}) permission = Permission.objects.get({'pk': item_properties['permission_id']})
except Permission.DoesNotExist: except Permission.DoesNotExist:
raise Http404 raise Http404
ct = get_object_or_404(ContentType, app_label=item_properties['requester_app_label'], model=item_properties['requester_model']) ct = get_object_or_404(ContentType, app_label=item_properties['requester_app_label'], model=item_properties['requester_model'])
requester_model = ct.model_class() requester_model = ct.model_class()
requester = get_object_or_404(requester_model, pk=item_properties['requester_id']) requester = get_object_or_404(requester_model, pk=item_properties['requester_id'])
items.append({'requester': requester, 'permission': permission}) items.append({'requester': requester, 'permission': permission})
sorted_items = sorted(items, key=operator.itemgetter('requester')) sorted_items = sorted(items, key=operator.itemgetter('requester'))
# Group items by requester # Group items by requester
groups = itertools.groupby(sorted_items, key=operator.itemgetter('requester')) groups = itertools.groupby(sorted_items, key=operator.itemgetter('requester'))
grouped_items = [(grouper, [permission['permission'] for permission in group_data]) for grouper, group_data in groups] grouped_items = [(grouper, [permission['permission'] for permission in group_data]) for grouper, group_data in groups]
# Warning: trial and error black magic ahead # Warning: trial and error black magic ahead
title_suffix = _(u' and ').join([_(u'%(permissions)s to %(requester)s') % {'permissions': ', '.join(['"%s"' % unicode(ps) for ps in p]), 'requester': unicode(r)} for r, p in grouped_items]) title_suffix = _(u' and ').join([_(u'%(permissions)s to %(requester)s') % {'permissions': ', '.join(['"%s"' % unicode(ps) for ps in p]), 'requester': unicode(r)} for r, p in grouped_items])
if len(grouped_items) == 1 and len(grouped_items[0][1]) == 1: if len(grouped_items) == 1 and len(grouped_items[0][1]) == 1:
permissions_label = _(u'permission') permissions_label = _(u'permission')
else: else:
@@ -238,7 +238,7 @@ def permission_revoke(request):
'permissions_label': permissions_label, 'permissions_label': permissions_label,
'title_suffix': title_suffix, 'title_suffix': title_suffix,
} }
if len(grouped_items) == 1: if len(grouped_items) == 1:
context['object'] = grouped_items[0][0] context['object'] = grouped_items[0][0]
@@ -259,7 +259,7 @@ def get_role_members(role, separate=False):
user_ct = ContentType.objects.get(model='user') user_ct = ContentType.objects.get(model='user')
group_ct = ContentType.objects.get(model='group') group_ct = ContentType.objects.get(model='group')
anonymous = ContentType.objects.get(model='anonymoususersingleton') anonymous = ContentType.objects.get(model='anonymoususersingleton')
users = role.members(filter_dict={'member_type': user_ct}) users = role.members(filter_dict={'member_type': user_ct})
groups = role.members(filter_dict={'member_type': group_ct}) groups = role.members(filter_dict={'member_type': group_ct})
anonymous = role.members(filter_dict={'member_type': anonymous}) anonymous = role.members(filter_dict={'member_type': anonymous})
@@ -268,34 +268,34 @@ def get_role_members(role, separate=False):
return users, groups, anonymous return users, groups, anonymous
else: else:
members = [] members = []
if users: if users:
members.append((_(u'Users'), _as_choice_list(list(users)))) members.append((_(u'Users'), _as_choice_list(list(users))))
if groups: if groups:
members.append((_(u'Groups'), _as_choice_list(list(groups)))) members.append((_(u'Groups'), _as_choice_list(list(groups))))
if anonymous: if anonymous:
members.append((_(u'Special'), _as_choice_list(list(anonymous)))) members.append((_(u'Special'), _as_choice_list(list(anonymous))))
return members return members
def get_non_role_members(role): def get_non_role_members(role):
#non members = all users - members - staff - super users #non members = all users - members - staff - super users
member_users, member_groups, member_anonymous = get_role_members(role, separate=True) member_users, member_groups, member_anonymous = get_role_members(role, separate=True)
staff_users = User.objects.filter(is_staff=True) staff_users = User.objects.filter(is_staff=True)
super_users = User.objects.filter(is_superuser=True) super_users = User.objects.filter(is_superuser=True)
users = set(User.objects.all()) - set(member_users) - set(staff_users) - set(super_users) users = set(User.objects.all()) - set(member_users) - set(staff_users) - set(super_users)
groups = set(Group.objects.all()) - set(member_groups) groups = set(Group.objects.all()) - set(member_groups)
anonymous = set([AnonymousUserSingleton.objects.get()]) - set(member_anonymous) anonymous = set([AnonymousUserSingleton.objects.get()]) - set(member_anonymous)
non_members = [] non_members = []
if users: if users:
non_members.append((_(u'Users'), _as_choice_list(list(users)))) non_members.append((_(u'Users'), _as_choice_list(list(users))))
if groups: if groups:
non_members.append((_(u'Groups'), _as_choice_list(list(groups)))) non_members.append((_(u'Groups'), _as_choice_list(list(groups))))
@@ -303,7 +303,7 @@ def get_non_role_members(role):
non_members.append((_(u'Special'), _as_choice_list(list(anonymous)))) non_members.append((_(u'Special'), _as_choice_list(list(anonymous))))
#non_holder_list.append((_(u'Special'), _as_choice_list([AnonymousUserSingleton.objects.get()]))) #non_holder_list.append((_(u'Special'), _as_choice_list([AnonymousUserSingleton.objects.get()])))
return non_members return non_members
+1
View File
@@ -2,6 +2,7 @@ from django.utils.translation import ugettext_lazy as _
from project_setup.api import register_setup from project_setup.api import register_setup
def is_superuser(context): def is_superuser(context):
return context['request'].user.is_staff or context['request'].user.is_superuser return context['request'].user.is_staff or context['request'].user.is_superuser
-1
View File
@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2 >>> 1 + 1 == 2
True True
"""} """}

Some files were not shown because too many files have changed in this diff Show More