Merge branch 'release/v0.12'

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

1
.gitignore vendored
View File

@@ -12,3 +12,4 @@ misc/mayan.geany
image_cache/
build/
_build/
gpg_home/

View File

@@ -4,6 +4,8 @@ source_lang = en
trans.es = apps/converter/locale/es/LC_MESSAGES/django.po
trans.pt = apps/converter/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/converter/locale/ru/LC_MESSAGES/django.po
trans.it = apps/converter/locale/it/LC_MESSAGES/django.po
trans.pl = apps/converter/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-common]
source_file = apps/common/locale/en/LC_MESSAGES/django.po
@@ -11,6 +13,8 @@ source_lang = en
trans.es = apps/common/locale/es/LC_MESSAGES/django.po
trans.pt = apps/common/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/common/locale/ru/LC_MESSAGES/django.po
trans.it = apps/common/locale/it/LC_MESSAGES/django.po
trans.pl = apps/common/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-permissions]
source_file = apps/permissions/locale/en/LC_MESSAGES/django.po
@@ -18,6 +22,8 @@ source_lang = en
trans.es = apps/permissions/locale/es/LC_MESSAGES/django.po
trans.pt = apps/permissions/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/permissions/locale/ru/LC_MESSAGES/django.po
trans.it = apps/permissions/locale/it/LC_MESSAGES/django.po
trans.pl = apps/permissions/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-sources]
source_file = apps/sources/locale/en/LC_MESSAGES/django.po
@@ -25,6 +31,8 @@ source_lang = en
trans.es = apps/sources/locale/es/LC_MESSAGES/django.po
trans.pt = apps/sources/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/sources/locale/ru/LC_MESSAGES/django.po
trans.it = apps/sources/locale/it/LC_MESSAGES/django.po
trans.pl = apps/sources/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-document_indexing]
source_file = apps/document_indexing/locale/en/LC_MESSAGES/django.po
@@ -32,6 +40,8 @@ source_lang = en
trans.es = apps/document_indexing/locale/es/LC_MESSAGES/django.po
trans.pt = apps/document_indexing/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/document_indexing/locale/ru/LC_MESSAGES/django.po
trans.it = apps/document_indexing/locale/it/LC_MESSAGES/django.po
trans.pl = apps/document_indexing/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-user_management]
source_file = apps/user_management/locale/en/LC_MESSAGES/django.po
@@ -39,6 +49,8 @@ source_lang = en
trans.es = apps/user_management/locale/es/LC_MESSAGES/django.po
trans.pt = apps/user_management/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/user_management/locale/ru/LC_MESSAGES/django.po
trans.it = apps/user_management/locale/it/LC_MESSAGES/django.po
trans.pl = apps/user_management/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-main]
source_file = apps/main/locale/en/LC_MESSAGES/django.po
@@ -46,6 +58,8 @@ source_lang = en
trans.es = apps/main/locale/es/LC_MESSAGES/django.po
trans.pt = apps/main/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/main/locale/ru/LC_MESSAGES/django.po
trans.it = apps/main/locale/it/LC_MESSAGES/django.po
trans.pl = apps/main/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-ocr]
source_file = apps/ocr/locale/en/LC_MESSAGES/django.po
@@ -53,6 +67,8 @@ source_lang = en
trans.es = apps/ocr/locale/es/LC_MESSAGES/django.po
trans.pt = apps/ocr/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/ocr/locale/ru/LC_MESSAGES/django.po
trans.it = apps/ocr/locale/it/LC_MESSAGES/django.po
trans.pl = apps/ocr/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-project_setup]
source_file = apps/project_setup/locale/en/LC_MESSAGES/django.po
@@ -60,6 +76,8 @@ source_lang = en
trans.es = apps/project_setup/locale/es/LC_MESSAGES/django.po
trans.pt = apps/project_setup/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/project_setup/locale/ru/LC_MESSAGES/django.po
trans.it = apps/project_setup/locale/it/LC_MESSAGES/django.po
trans.pl = apps/project_setup/locale/pl/LC_MESSAGES/django.po
[main]
host = https://www.transifex.net
@@ -70,6 +88,8 @@ source_lang = en
trans.es = apps/folders/locale/es/LC_MESSAGES/django.po
trans.pt = apps/folders/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/folders/locale/ru/LC_MESSAGES/django.po
trans.it = apps/folders/locale/it/LC_MESSAGES/django.po
trans.pl = apps/folders/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-history]
source_file = apps/history/locale/en/LC_MESSAGES/django.po
@@ -77,6 +97,8 @@ source_lang = en
trans.es = apps/history/locale/es/LC_MESSAGES/django.po
trans.pt = apps/history/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/history/locale/ru/LC_MESSAGES/django.po
trans.it = apps/history/locale/it/LC_MESSAGES/django.po
trans.pl = apps/history/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-dynamic_search]
source_file = apps/dynamic_search/locale/en/LC_MESSAGES/django.po
@@ -84,6 +106,8 @@ source_lang = en
trans.es = apps/dynamic_search/locale/es/LC_MESSAGES/django.po
trans.pt = apps/dynamic_search/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/dynamic_search/locale/ru/LC_MESSAGES/django.po
trans.it = apps/dynamic_search/locale/it/LC_MESSAGES/django.po
trans.pl = apps/dynamic_search/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-smart_settings]
source_file = apps/smart_settings/locale/en/LC_MESSAGES/django.po
@@ -91,6 +115,8 @@ source_lang = en
trans.es = apps/smart_settings/locale/es/LC_MESSAGES/django.po
trans.pt = apps/smart_settings/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/smart_settings/locale/ru/LC_MESSAGES/django.po
trans.it = apps/smart_settings/locale/it/LC_MESSAGES/django.po
trans.pl = apps/smart_settings/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-navigation]
source_file = apps/navigation/locale/en/LC_MESSAGES/django.po
@@ -98,6 +124,8 @@ source_lang = en
trans.es = apps/navigation/locale/es/LC_MESSAGES/django.po
trans.pt = apps/navigation/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/navigation/locale/ru/LC_MESSAGES/django.po
trans.it = apps/navigation/locale/it/LC_MESSAGES/django.po
trans.pl = apps/navigation/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-tags]
source_file = apps/tags/locale/en/LC_MESSAGES/django.po
@@ -105,6 +133,8 @@ source_lang = en
trans.es = apps/tags/locale/es/LC_MESSAGES/django.po
trans.pt = apps/tags/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/tags/locale/ru/LC_MESSAGES/django.po
trans.it = apps/tags/locale/it/LC_MESSAGES/django.po
trans.pl = apps/tags/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-documents]
source_file = apps/documents/locale/en/LC_MESSAGES/django.po
@@ -112,6 +142,8 @@ source_lang = en
trans.es = apps/documents/locale/es/LC_MESSAGES/django.po
trans.pt = apps/documents/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/documents/locale/ru/LC_MESSAGES/django.po
trans.it = apps/documents/locale/it/LC_MESSAGES/django.po
trans.pl = apps/documents/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-project_tools]
source_file = apps/project_tools/locale/en/LC_MESSAGES/django.po
@@ -119,6 +151,8 @@ source_lang = en
trans.es = apps/project_tools/locale/es/LC_MESSAGES/django.po
trans.pt = apps/project_tools/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/project_tools/locale/ru/LC_MESSAGES/django.po
trans.it = apps/project_tools/locale/it/LC_MESSAGES/django.po
trans.pl = apps/project_tools/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-linking]
source_file = apps/linking/locale/en/LC_MESSAGES/django.po
@@ -126,6 +160,8 @@ source_lang = en
trans.es = apps/linking/locale/es/LC_MESSAGES/django.po
trans.pt = apps/linking/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/linking/locale/ru/LC_MESSAGES/django.po
trans.it = apps/linking/locale/it/LC_MESSAGES/django.po
trans.pl = apps/linking/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-document_comments]
source_file = apps/document_comments/locale/en/LC_MESSAGES/django.po
@@ -133,6 +169,8 @@ source_lang = en
trans.es = apps/document_comments/locale/es/LC_MESSAGES/django.po
trans.pt = apps/document_comments/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/document_comments/locale/ru/LC_MESSAGES/django.po
trans.it = apps/document_comments/locale/it/LC_MESSAGES/django.po
trans.pl = apps/document_comments/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-metadata]
source_file = apps/metadata/locale/en/LC_MESSAGES/django.po
@@ -140,6 +178,8 @@ source_lang = en
trans.es = apps/metadata/locale/es/LC_MESSAGES/django.po
trans.pt = apps/metadata/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/metadata/locale/ru/LC_MESSAGES/django.po
trans.it = apps/metadata/locale/it/LC_MESSAGES/django.po
trans.pl = apps/metadata/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-web_theme]
source_file = apps/web_theme/locale/en/LC_MESSAGES/django.po
@@ -147,6 +187,8 @@ source_lang = en
trans.es = apps/web_theme/locale/es/LC_MESSAGES/django.po
trans.pt = apps/web_theme/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/web_theme/locale/ru/LC_MESSAGES/django.po
trans.it = apps/web_theme/locale/it/LC_MESSAGES/django.po
trans.pl = apps/web_theme/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-django_gpg]
source_file = apps/django_gpg/locale/en/LC_MESSAGES/django.po
@@ -154,3 +196,32 @@ source_lang = en
trans.es = apps/django_gpg/locale/es/LC_MESSAGES/django.po
trans.pt = apps/django_gpg/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/django_gpg/locale/ru/LC_MESSAGES/django.po
trans.it = apps/django_gpg/locale/it/LC_MESSAGES/django.po
trans.pl = apps/django_gpg/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-document_signatures]
source_file = apps/document_signatures/locale/en/LC_MESSAGES/django.po
source_lang = en
trans.es = apps/document_signatures/locale/es/LC_MESSAGES/django.po
trans.pt = apps/document_signatures/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/document_signatures/locale/ru/LC_MESSAGES/django.po
trans.it = apps/document_signatures/locale/it/LC_MESSAGES/django.po
trans.pl = apps/document_signatures/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-acls]
source_file = apps/acls/locale/en/LC_MESSAGES/django.po
source_lang = en
trans.es = apps/acls/locale/es/LC_MESSAGES/django.po
trans.pt = apps/acls/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/acls/locale/ru/LC_MESSAGES/django.po
trans.it = apps/acls/locale/it/LC_MESSAGES/django.po
trans.pl = apps/acls/locale/pl/LC_MESSAGES/django.po
[mayan-edms.apps-feedback]
source_file = apps/feedback/locale/en/LC_MESSAGES/django.po
source_lang = en
trans.es = apps/feedback/locale/es/LC_MESSAGES/django.po
trans.pt = apps/feedback/locale/pt/LC_MESSAGES/django.po
trans.ru = apps/feedback/locale/ru/LC_MESSAGES/django.po
trans.it = apps/feedback/locale/it/LC_MESSAGES/django.po
trans.pl = apps/feedback/locale/pl/LC_MESSAGES/django.po

View File

@@ -3,9 +3,7 @@ Mayan
Open source, Django based document manager with custom metadata indexing, file serving integration and OCR capabilities.
[Website](http://www.mayan-edms.com)
[Mailing list (via Google Groups)](http://groups.google.com/group/mayan-edms)
[Website](http://bit.ly/mayan-edms)
[Video demostration](http://bit.ly/pADNXv)
@@ -13,6 +11,7 @@ Open source, Django based document manager with custom metadata indexing, file s
[Translations](https://www.transifex.net/projects/p/mayan-edms/)
[Mailing list (via Google Groups)](http://groups.google.com/group/mayan-edms)
License
-------

View File

@@ -0,0 +1,2 @@
from main import (__version__, __author__, __copyright__, __credits__,
__license__, __maintainer__, __email__, __status__)

39
apps/acls/__init__.py Normal file
View File

@@ -0,0 +1,39 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from navigation.api import register_links, register_multi_item_links
from project_setup.api import register_setup
from .classes import (AccessHolder, AccessObjectClass, ClassAccessHolder,
AccessObject)
from .permissions import (ACLS_EDIT_ACL, ACLS_VIEW_ACL,
ACLS_CLASS_EDIT_ACL, ACLS_CLASS_VIEW_ACL)
acl_list = {'text': _(u'ACLs'), 'view': 'acl_list', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
acl_detail = {'text': _(u'details'), 'view': 'acl_detail', 'args': ['access_object.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_VIEW_ACL]}
acl_grant = {'text': _(u'grant'), 'view': 'acl_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_EDIT_ACL]}
acl_revoke = {'text': _(u'revoke'), 'view': 'acl_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_EDIT_ACL]}
acl_holder_new = {'text': _(u'New holder'), 'view': 'acl_holder_new', 'args': 'access_object.gid', 'famfam': 'user', 'permissions': [ACLS_EDIT_ACL]}
acl_setup_valid_classes = {'text': _(u'Default ACLs'), 'view': 'acl_setup_valid_classes', 'icon': 'lock.png', 'permissions': [ACLS_CLASS_VIEW_ACL], 'children_view_regex': [r'^acl_class', r'^acl_setup']}
acl_class_list = {'text': _(u'List of classes'), 'view': 'acl_setup_valid_classes', 'famfam': 'package', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_list = {'text': _(u'ACLs for class'), 'view': 'acl_class_acl_list', 'args': 'object.gid', 'famfam': 'lock_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_detail = {'text': _(u'details'), 'view': 'acl_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'key_go', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_new_holder_for = {'text': _(u'New holder'), 'view': 'acl_class_new_holder_for', 'args': 'object.gid', 'famfam': 'user', 'permissions': [ACLS_CLASS_EDIT_ACL]}
acl_class_grant = {'text': _(u'grant'), 'view': 'acl_class_multiple_grant', 'famfam': 'key_add', 'permissions': [ACLS_CLASS_EDIT_ACL]}
acl_class_revoke = {'text': _(u'revoke'), 'view': 'acl_class_multiple_revoke', 'famfam': 'key_delete', 'permissions': [ACLS_CLASS_EDIT_ACL]}
register_links(AccessHolder, [acl_detail])
register_multi_item_links(['acl_detail'], [acl_grant, acl_revoke])
register_links([AccessObject], [acl_holder_new], menu_name='sidebar')
register_setup(acl_setup_valid_classes)
register_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acl_class_acl_detail', 'acl_class_multiple_grant', 'acl_class_multiple_revoke'], [acl_class_list], menu_name='secondary_menu')
register_links(ClassAccessHolder, [acl_class_acl_detail])
register_links(AccessObjectClass, [acl_class_acl_list, acl_class_new_holder_for])
register_multi_item_links(['acl_class_acl_detail'], [acl_class_grant, acl_class_revoke])

23
apps/acls/admin.py Normal file
View File

@@ -0,0 +1,23 @@
from __future__ import absolute_import
from django.contrib import admin
from .models import AccessEntry
#class PermissionHolderInline(admin.StackedInline):
# model = PermissionHolder
# extra = 1
# classes = ('collapse-open',)
# allow_add = True#
#
class AccessEntryAdmin(admin.ModelAdmin):
related_lookup_fields = {
'generic': [['holder_type', 'holder_id'], ['content_type', 'object_id']],
}
#inlines = [PermissionHolderInline]
list_display = ('pk', 'holder_object', 'permission', 'content_object')
list_display_links = ('pk',)
model = AccessEntry
admin.site.register(AccessEntry, AccessEntryAdmin)

28
apps/acls/api.py Normal file
View File

@@ -0,0 +1,28 @@
from __future__ import absolute_import
from django.contrib.contenttypes.models import ContentType
_class_permissions = {}
def class_permissions(cls, permission_list):
"""
Associate a permissions list to a class
"""
stored_permissions = _class_permissions.setdefault(cls, [])
stored_permissions.extend(permission_list)
def get_class_permissions_for(obj):
"""
Return a list of permissions associated with a content type
"""
content_type = ContentType.objects.get_for_model(obj)
return _class_permissions.get(content_type.model_class(), [])
def get_classes():
"""
Return a list of encapsulated classes that have been registered
"""
return _class_permissions.keys()

158
apps/acls/classes.py Normal file
View File

@@ -0,0 +1,158 @@
from __future__ import absolute_import
import logging
import sys
import types
from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase
from django.template.defaultfilters import capfirst
from django.core.exceptions import ObjectDoesNotExist
from common.models import AnonymousUserSingleton
logger = logging.getLogger(__name__)
_cache = {}
def get_source_object(obj):
if isinstance(obj, EncapsulatedObject):
return obj.source_object
else:
return obj
class EncapsulatedObject(object):
source_object_name = u'source_object'
@classmethod
def object_key(cls, app_label=None, model=None, pk=None):
if pk:
return '%s.%s.%s.%s' % (cls.__name__, app_label, model, pk)
else:
return '%s.%s.%s' % (cls.__name__, app_label, model)
@classmethod
def add_to_class(cls, name, value):
if hasattr(value, 'contribute_to_class'):
value.contribute_to_class(cls, name)
else:
setattr(cls, name, value)
@classmethod
def set_source_object_name(cls, new_name):
cls.source_object_name = new_name
#@classmethod
#def encapsulate_list(cls, source_object=None, app_label=None, model=None, pk=None):
@classmethod
def encapsulate(cls, source_object):
source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
content_type = ContentType.objects.get_for_model(source_object)
if hasattr(source_object, 'pk'):
# Object
object_key = cls.object_key(content_type.app_label, content_type.model, source_object.pk)
else:
# Class
object_key = cls.object_key(content_type.app_label, content_type.model)
try:
return _cache[object_key]
except KeyError:
encapsulated_object = cls(source_object)
_cache[object_key] = encapsulated_object
return encapsulated_object
@classmethod
def get(cls, gid):
elements = gid.split('.')
if len(elements) == 3:
app_label, model, pk = elements[0], elements[1], elements[2]
elif len(elements) == 2:
app_label, model = elements[0], elements[1]
pk = None
object_key = cls.object_key(*elements)
try:
return _cache[object_key]
except KeyError:
try:
content_type = ContentType.objects.get(app_label=app_label, model=model)
except ContentType.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
raise ObjectDoesNotExist("%s matching query does not exist." % ContentType._meta.object_name)
else:
source_object_model_class = content_type.model_class()
if pk:
try:
source_object = content_type.get_object_for_this_type(pk=pk)
except source_object_model_class.DoesNotExist:
#cls.add_to_class('DoesNotExist', subclass_exception('DoesNotExist', (ObjectDoesNotExist,), cls.__name__))
#raise cls.DoesNotExist("%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:
source_object = source_object_model_class
return cls.encapsulate(source_object)
def __init__(self, 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.model)
if isinstance(source_object, ModelBase):
# Class
self.gid = '%s.%s' % (self.content_type.app_label, self.content_type.model)
else:
# Object
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)
def __unicode__(self):
if isinstance(self.source_object, ModelBase):
return capfirst(unicode(self.source_object._meta.verbose_name_plural))
elif self.ct_fullname == 'auth.user':
return u'%s %s' % (self.source_object._meta.verbose_name, self.source_object.get_full_name())
elif self.ct_fullname == 'common.anonymoususersingleton':
return unicode(self.source_object)
elif self.ct_fullname == 'acls.creatorsingleton':
return unicode(self.source_object)
else:
return u'%s %s' % (self.source_object._meta.verbose_name, self.source_object)
def __repr__(self):
return self.__unicode__()
@property
def source_object(self):
return getattr(self, self.__class__.source_object_name, None)
class AccessHolder(EncapsulatedObject):
source_object_name = u'holder_object'
class AccessObject(EncapsulatedObject):
source_object_name = u'obj'
class AccessObjectClass(EncapsulatedObject):
source_object_name = u'cls'
class ClassAccessHolder(EncapsulatedObject):
source_object_name = u'class_holder'
if sys.version_info < (2, 5):
# Prior to Python 2.5, Exception was an old-style class
def subclass_exception(name, parents, unused):
return types.ClassType(name, parents, {})
else:
def subclass_exception(name, parents, module):
return type(name, parents, {'__module__': module})

58
apps/acls/forms.py Normal file
View File

@@ -0,0 +1,58 @@
from __future__ import absolute_import
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User, Group
from permissions.models import Role
from common.utils import get_object_name
from common.models import AnonymousUserSingleton
from .classes import AccessHolder
from .models import CreatorSingleton
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])
class BaseHolderSelectionForm(forms.Form):
holder_gid = forms.ChoiceField(
label=_(u'New holder')
)
def __init__(self, *args, **kwargs):
current_holders = kwargs.pop('current_holders', [])
if current_holders:
current_holders = [holder.source_object for holder in current_holders]
staff_users = User.objects.filter(is_staff=True)
super_users = User.objects.filter(is_superuser=True)
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)
groups = set(Group.objects.all()) - set(current_holders)
special = set(self.special_holders) - set(current_holders)
non_holder_list = []
if users:
non_holder_list.append((_(u'Users'), _as_choice_list(list(users))))
if groups:
non_holder_list.append((_(u'Groups'), _as_choice_list(list(groups))))
if roles:
non_holder_list.append((_(u'Roles'), _as_choice_list(list(roles))))
if special:
non_holder_list.append((_(u'Special'), _as_choice_list(list(special))))
super(BaseHolderSelectionForm, self).__init__(*args, **kwargs)
self.fields['holder_gid'].choices = non_holder_list
class HolderSelectionForm(BaseHolderSelectionForm):
special_holders = [AnonymousUserSingleton.objects.get()]
class ClassHolderSelectionForm(BaseHolderSelectionForm):
special_holders = [AnonymousUserSingleton.objects.get(), CreatorSingleton.objects.get()]

13
apps/acls/literals.py Normal file
View File

@@ -0,0 +1,13 @@
# Content type <-> fam fam icon mapping
CONTENT_TYPE_ICON_MAP = {
'auth.user': 'user',
'auth.group': 'group',
'documents.document': 'page',
'permissions.role': 'medal_gold_1',
'folders.folder': 'folder',
'taggit.tag': 'tag_blue',
'linking.smartlink': 'page_link',
'common.anonymoususersingleton': 'user',
'acls.creatorsingleton': 'user',
}

View File

@@ -0,0 +1,241 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: __init__.py:14
msgid "ACLs"
msgstr ""
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr ""
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr ""
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr ""
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr ""
#: __init__.py:20
msgid "Default ACLs"
msgstr ""
#: __init__.py:21
msgid "List of classes"
msgstr ""
#: __init__.py:22
msgid "ACLs for class"
msgstr ""
#: forms.py:38
msgid "Users"
msgstr ""
#: forms.py:41
msgid "Groups"
msgstr ""
#: forms.py:44
msgid "Roles"
msgstr ""
#: forms.py:47
msgid "Special"
msgstr ""
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr ""
#: models.py:27 models.py:69
msgid "permission"
msgstr ""
#: models.py:53
msgid "access entry"
msgstr ""
#: models.py:54
msgid "access entries"
msgstr ""
#: models.py:90
msgid "default access entry"
msgstr ""
#: models.py:91
msgid "default access entries"
msgstr ""
#: models.py:109
msgid "Creator"
msgstr ""
#: models.py:112 models.py:113
msgid "creator"
msgstr ""
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr ""
#: permissions.py:10
msgid "Edit ACLs"
msgstr ""
#: permissions.py:11
msgid "View ACLs"
msgstr ""
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr ""
#: permissions.py:14
msgid "View class default ACLs"
msgstr ""
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr ""
#: views.py:49 views.py:411
msgid "holder"
msgstr ""
#: views.py:50 views.py:412
msgid "permissions"
msgstr ""
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr ""
#: views.py:104 views.py:444
msgid "namespace"
msgstr ""
#: views.py:105 views.py:445
msgid "label"
msgstr ""
#: views.py:107 views.py:447
msgid "has permission"
msgstr ""
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ""
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr ""
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr ""
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr ""
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr ""
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr ""
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr ""
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr ""
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr ""
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr ""
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr ""
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr ""
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr ""
#: views.py:356 views.py:488
msgid "Select"
msgstr ""
#: views.py:388
msgid "classes"
msgstr ""
#: views.py:390
msgid "class"
msgstr ""
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr ""
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr ""
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,244 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-12 00:16+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/"
"mayan-edms/team/es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14
msgid "ACLs"
msgstr "LCA"
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr "detalles"
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr "otorgar"
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr "revocar"
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr "Nuevo titular"
#: __init__.py:20
msgid "Default ACLs"
msgstr "LCA por defecto"
#: __init__.py:21
msgid "List of classes"
msgstr "Lista de clases"
#: __init__.py:22
msgid "ACLs for class"
msgstr "LCA para la clase"
#: forms.py:38
msgid "Users"
msgstr "Usuarios"
#: forms.py:41
msgid "Groups"
msgstr "Grupos"
#: forms.py:44
msgid "Roles"
msgstr "Funciones"
#: forms.py:47
msgid "Special"
msgstr "Especial"
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr "Acceso insuficiente."
#: models.py:27 models.py:69
msgid "permission"
msgstr "permiso"
#: models.py:53
msgid "access entry"
msgstr "entrada de acceso"
#: models.py:54
msgid "access entries"
msgstr "entradas de acceso"
#: models.py:90
msgid "default access entry"
msgstr "entrada de acceso por defecto"
#: models.py:91
msgid "default access entries"
msgstr "entradas de acceso por defecto"
#: models.py:109
msgid "Creator"
msgstr "Creador"
#: models.py:112 models.py:113
msgid "creator"
msgstr "creador"
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr "Listas de control de acceso"
#: permissions.py:10
msgid "Edit ACLs"
msgstr "Editar LCA"
#: permissions.py:11
msgid "View ACLs"
msgstr "Ver LCA"
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr "Editar LCA por defecto de la clase"
#: permissions.py:14
msgid "View class default ACLs"
msgstr "Ver LCA por defecto de la clase"
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr "listas de control de acceso para: %s"
#: views.py:49 views.py:411
msgid "holder"
msgstr "titular"
#: views.py:50 views.py:412
msgid "permissions"
msgstr "permisos"
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr "permisos disponibles a: %(actor)s para %(obj)s "
#: views.py:104 views.py:444
msgid "namespace"
msgstr "espacio de nombres"
#: views.py:105 views.py:445
msgid "label"
msgstr "etiqueta"
#: views.py:107 views.py:447
msgid "has permission"
msgstr "tiene permiso"
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ", "
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr " para %s"
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr " a %s"
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr "¿Está seguro que desea conceder el permiso %(title_suffix)s?"
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr "¿Está seguro que desea conceder los permisos de %(title_suffix)s?"
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr "Permiso \"%(permission)s\" otorgado a %(actor)s para %(object)s."
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr ""
"%(actor)s, ya tenía el permiso \"%(permission)s\", otorgado para %(object)s."
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr " de %s"
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr "¿Está seguro que desea revocar el permiso %(title_suffix)s?"
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr "¿Está seguro de querer revocar los permisos %(title_suffix)s?"
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr "Permiso \"%(permission)s\" revocado del %(actor)s para %(object)s."
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr "%(actor)s, no tenía el permiso \"%(permission)s\" para %(object)s."
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr "añadir nuevo titular para: %s"
#: views.py:356 views.py:488
msgid "Select"
msgstr "Seleccionar"
#: views.py:388
msgid "classes"
msgstr "clases"
#: views.py:390
msgid "class"
msgstr "clase"
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr "listas de control de acceso por defecto para la clase: %s"
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr "permisos disponibles para: %(actor)s para la clase %(class)s "
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr "añadir nuevo titular para la clase: %s"

Binary file not shown.

View File

@@ -0,0 +1,242 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-21 00:41+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14
msgid "ACLs"
msgstr ""
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr "dettagli"
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr "concedere"
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr "revocare"
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr ""
#: __init__.py:20
msgid "Default ACLs"
msgstr ""
#: __init__.py:21
msgid "List of classes"
msgstr ""
#: __init__.py:22
msgid "ACLs for class"
msgstr ""
#: forms.py:38
msgid "Users"
msgstr "Utenti"
#: forms.py:41
msgid "Groups"
msgstr "Gruppi"
#: forms.py:44
msgid "Roles"
msgstr ""
#: forms.py:47
msgid "Special"
msgstr "Speciale"
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr ""
#: models.py:27 models.py:69
msgid "permission"
msgstr "autorizzazione"
#: models.py:53
msgid "access entry"
msgstr ""
#: models.py:54
msgid "access entries"
msgstr ""
#: models.py:90
msgid "default access entry"
msgstr ""
#: models.py:91
msgid "default access entries"
msgstr ""
#: models.py:109
msgid "Creator"
msgstr "Creatore"
#: models.py:112 models.py:113
msgid "creator"
msgstr "creatore"
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr ""
#: permissions.py:10
msgid "Edit ACLs"
msgstr ""
#: permissions.py:11
msgid "View ACLs"
msgstr ""
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr ""
#: permissions.py:14
msgid "View class default ACLs"
msgstr ""
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr ""
#: views.py:49 views.py:411
msgid "holder"
msgstr ""
#: views.py:50 views.py:412
msgid "permissions"
msgstr "le autorizzazioni"
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr "autorizzazioni disponibili per: %(actor)s per %(obj)s "
#: views.py:104 views.py:444
msgid "namespace"
msgstr ""
#: views.py:105 views.py:445
msgid "label"
msgstr ""
#: views.py:107 views.py:447
msgid "has permission"
msgstr "ha l'autorizzazione"
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ", "
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr "per %s"
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr "a %s"
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr "Sei sicuro di voler concedere l'autorizzazione %(title_suffix)s?"
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr "Sei sicuro di voler concedere permessi %(title_suffix)s?"
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr ""
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr ""
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr "da %s"
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr "Sei sicuro di voler revocare l'autorizzazione %(title_suffix)s?"
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr "Sei sicuro di voler revocare permessi %(title_suffix)s?"
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr ""
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr ""
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr ""
#: views.py:356 views.py:488
msgid "Select"
msgstr "Selezionare"
#: views.py:388
msgid "classes"
msgstr ""
#: views.py:390
msgid "class"
msgstr ""
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr ""
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr ""
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,241 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-01-02 09:45+0000\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: Polish (http://www.transifex.net/projects/p/mayan-edms/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:14
msgid "ACLs"
msgstr ""
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr ""
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr ""
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr ""
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr ""
#: __init__.py:20
msgid "Default ACLs"
msgstr ""
#: __init__.py:21
msgid "List of classes"
msgstr ""
#: __init__.py:22
msgid "ACLs for class"
msgstr ""
#: forms.py:38
msgid "Users"
msgstr ""
#: forms.py:41
msgid "Groups"
msgstr ""
#: forms.py:44
msgid "Roles"
msgstr ""
#: forms.py:47
msgid "Special"
msgstr ""
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr ""
#: models.py:27 models.py:69
msgid "permission"
msgstr ""
#: models.py:53
msgid "access entry"
msgstr ""
#: models.py:54
msgid "access entries"
msgstr ""
#: models.py:90
msgid "default access entry"
msgstr ""
#: models.py:91
msgid "default access entries"
msgstr ""
#: models.py:109
msgid "Creator"
msgstr ""
#: models.py:112 models.py:113
msgid "creator"
msgstr ""
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr ""
#: permissions.py:10
msgid "Edit ACLs"
msgstr ""
#: permissions.py:11
msgid "View ACLs"
msgstr ""
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr ""
#: permissions.py:14
msgid "View class default ACLs"
msgstr ""
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr ""
#: views.py:49 views.py:411
msgid "holder"
msgstr ""
#: views.py:50 views.py:412
msgid "permissions"
msgstr ""
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr ""
#: views.py:104 views.py:444
msgid "namespace"
msgstr ""
#: views.py:105 views.py:445
msgid "label"
msgstr ""
#: views.py:107 views.py:447
msgid "has permission"
msgstr ""
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ""
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr ""
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr ""
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr ""
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr ""
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr ""
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr ""
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr ""
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr ""
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr ""
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr ""
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr ""
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr ""
#: views.py:356 views.py:488
msgid "Select"
msgstr ""
#: views.py:388
msgid "classes"
msgstr ""
#: views.py:390
msgid "class"
msgstr ""
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr ""
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr ""
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,242 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:20+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/"
"team/pt/)\n"
"Language: pt\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14
msgid "ACLs"
msgstr ""
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr ""
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr ""
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr ""
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr ""
#: __init__.py:20
msgid "Default ACLs"
msgstr ""
#: __init__.py:21
msgid "List of classes"
msgstr ""
#: __init__.py:22
msgid "ACLs for class"
msgstr ""
#: forms.py:38
msgid "Users"
msgstr ""
#: forms.py:41
msgid "Groups"
msgstr ""
#: forms.py:44
msgid "Roles"
msgstr ""
#: forms.py:47
msgid "Special"
msgstr ""
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr ""
#: models.py:27 models.py:69
msgid "permission"
msgstr ""
#: models.py:53
msgid "access entry"
msgstr ""
#: models.py:54
msgid "access entries"
msgstr ""
#: models.py:90
msgid "default access entry"
msgstr ""
#: models.py:91
msgid "default access entries"
msgstr ""
#: models.py:109
msgid "Creator"
msgstr ""
#: models.py:112 models.py:113
msgid "creator"
msgstr ""
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr ""
#: permissions.py:10
msgid "Edit ACLs"
msgstr ""
#: permissions.py:11
msgid "View ACLs"
msgstr ""
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr ""
#: permissions.py:14
msgid "View class default ACLs"
msgstr ""
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr ""
#: views.py:49 views.py:411
msgid "holder"
msgstr ""
#: views.py:50 views.py:412
msgid "permissions"
msgstr ""
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr ""
#: views.py:104 views.py:444
msgid "namespace"
msgstr ""
#: views.py:105 views.py:445
msgid "label"
msgstr ""
#: views.py:107 views.py:447
msgid "has permission"
msgstr ""
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ""
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr ""
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr ""
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr ""
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr ""
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr ""
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr ""
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr ""
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr ""
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr ""
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr ""
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr ""
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr ""
#: views.py:356 views.py:488
msgid "Select"
msgstr ""
#: views.py:388
msgid "classes"
msgstr ""
#: views.py:390
msgid "class"
msgstr ""
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr ""
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr ""
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,242 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Sergey Glita <gsv70@mail.ru>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-27 04:26+0000\n"
"Last-Translator: Sergey Glita <gsv70@mail.ru>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/language/ru/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:14
msgid "ACLs"
msgstr "Списки ACL"
#: __init__.py:15 __init__.py:23
msgid "details"
msgstr "детали"
#: __init__.py:16 __init__.py:25
msgid "grant"
msgstr "предоставить"
#: __init__.py:17 __init__.py:26
msgid "revoke"
msgstr "отозвать"
#: __init__.py:18 __init__.py:24 forms.py:21
msgid "New holder"
msgstr "Новый владелец"
#: __init__.py:20
msgid "Default ACLs"
msgstr "ACL по умолчанию"
#: __init__.py:21
msgid "List of classes"
msgstr "Список классов"
#: __init__.py:22
msgid "ACLs for class"
msgstr "ACL для класса"
#: forms.py:38
msgid "Users"
msgstr "Пользователи"
#: forms.py:41
msgid "Groups"
msgstr "Группы"
#: forms.py:44
msgid "Roles"
msgstr "Роли"
#: forms.py:47
msgid "Special"
msgstr "Специальный"
#: managers.py:116 managers.py:128
msgid "Insufficient access."
msgstr "Недостаточный доступ."
#: models.py:27 models.py:69
msgid "permission"
msgstr "разрешение"
#: models.py:53
msgid "access entry"
msgstr "запись доступа"
#: models.py:54
msgid "access entries"
msgstr "записи доступа"
#: models.py:90
msgid "default access entry"
msgstr "запись доступа по умолчанию"
#: models.py:91
msgid "default access entries"
msgstr "записи доступа по умолчанию"
#: models.py:109
msgid "Creator"
msgstr "Создатель"
#: models.py:112 models.py:113
msgid "creator"
msgstr "создатель"
#: permissions.py:7 permissions.py:8
msgid "Access control lists"
msgstr "Списки контроля доступа"
#: permissions.py:10
msgid "Edit ACLs"
msgstr "Редактировать списки ACL"
#: permissions.py:11
msgid "View ACLs"
msgstr "Просмотр списков ACL"
#: permissions.py:13
msgid "Edit class default ACLs"
msgstr "Редактировать списки ACL класса по умолчанию"
#: permissions.py:14
msgid "View class default ACLs"
msgstr "Просмотр списков ACL класса по умолчанию"
#: views.py:47
#, python-format
msgid "access control lists for: %s"
msgstr "списки контроля доступа для %s"
#: views.py:49 views.py:411
msgid "holder"
msgstr "владелец"
#: views.py:50 views.py:412
msgid "permissions"
msgstr "разрешения"
#: views.py:97
#, python-format
msgid "permissions available to: %(actor)s for %(obj)s"
msgstr "разрешения, доступные %(actor)s для %(obj)s"
#: views.py:104 views.py:444
msgid "namespace"
msgstr "пространство имен"
#: views.py:105 views.py:445
msgid "label"
msgstr "этикетка"
#: views.py:107 views.py:447
msgid "has permission"
msgstr "имеет разрешение"
#: views.py:185 views.py:279 views.py:528 views.py:608
msgid ", "
msgstr ","
#: views.py:186 views.py:280 views.py:529 views.py:609
#, python-format
msgid " for %s"
msgstr "для %s"
#: views.py:187 views.py:530
#, python-format
msgid " to %s"
msgstr "до %s"
#: views.py:190 views.py:533
#, python-format
msgid "Are you sure you wish to grant the permission %(title_suffix)s?"
msgstr "Вы действительно хотите предоставить разрешение %(title_suffix)s?"
#: views.py:192 views.py:535
#, python-format
msgid "Are you sure you wish to grant the permissions %(title_suffix)s?"
msgstr "Вы уверены, что хотите предоставить разрешения %(title_suffix)s?"
#: views.py:199 views.py:542
#, python-format
msgid "Permission \"%(permission)s\" granted to %(actor)s for %(object)s."
msgstr "Право \"%(permission)s\" проедоставлено %(actor)s для %(object)s."
#: views.py:205 views.py:548
#, python-format
msgid ""
"%(actor)s, already had the permission \"%(permission)s\" granted for "
"%(object)s."
msgstr "%(actor)s, уже имеет право \"%(permission)s\" для %(object)s."
#: views.py:281 views.py:610
#, python-format
msgid " from %s"
msgstr "от%s"
#: views.py:284 views.py:613
#, python-format
msgid "Are you sure you wish to revoke the permission %(title_suffix)s?"
msgstr "Вы уверены, что хотите отменить разрешение %(title_suffix)s?"
#: views.py:286 views.py:615
#, python-format
msgid "Are you sure you wish to revoke the permissions %(title_suffix)s?"
msgstr "Вы уверены, что хотите отменить разрешение %(title_suffix)s?"
#: views.py:293 views.py:622
#, python-format
msgid "Permission \"%(permission)s\" revoked of %(actor)s for %(object)s."
msgstr "Право \"%(permission)s\" для %(object)s отозвано у %(actor)s."
#: views.py:299 views.py:628
#, python-format
msgid "%(actor)s, didn't had the permission \"%(permission)s\" for %(object)s."
msgstr "%(actor)s не имеет права \"%(permission)s\" для %(object)s."
#: views.py:355
#, python-format
msgid "add new holder for: %s"
msgstr "добавить нового владельца для %s"
#: views.py:356 views.py:488
msgid "Select"
msgstr "Выбор"
#: views.py:388
msgid "classes"
msgstr "классы"
#: views.py:390
msgid "class"
msgstr "класс"
#: views.py:409
#, python-format
msgid "default access control lists for class: %s"
msgstr "списки контроля доступа умолчанию для класса %s"
#: views.py:437
#, python-format
msgid "permissions available to: %(actor)s for class %(class)s"
msgstr "разрешения доступные %(actor)s для класса %(class)s"
#: views.py:486
#, python-format
msgid "add new holder for class: %s"
msgstr "добавить нового владельца для класса %s"

325
apps/acls/managers.py Normal file
View File

@@ -0,0 +1,325 @@
from __future__ import absolute_import
import logging
from django.db import models
from django.utils.translation import ugettext
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from django.core.urlresolvers import reverse
from django.db.models import Q
from common.models import AnonymousUserSingleton
from permissions.models import Permission, RoleMember
from .classes import AccessHolder, ClassAccessHolder, get_source_object
logger = logging.getLogger(__name__)
class AccessEntryManager(models.Manager):
"""
Implement a 3 tier permission system, involving a permissions, an actor
and an object
"""
def grant(self, permission, actor, obj):
"""
Grant a permission (what), (to) an actor, (on) a specific object
"""
obj = get_source_object(obj)
actor = get_source_object(actor)
access_entry, created = self.model.objects.get_or_create(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk
)
return created
def revoke(self, permission, actor, obj):
"""
Revoke a permission (what), (from) an actor, (on) a specific object
"""
obj = get_source_object(obj)
actor = get_source_object(actor)
try:
access_entry = self.model.objects.get(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk
)
except self.model.DoesNotExist:
return False
else:
access_entry.delete()
return True
def has_access(self, permission, actor, obj, db_only=False):
"""
Returns whether an actor has a specific permission for an object
"""
obj = get_source_object(obj)
actor = get_source_object(actor)
if isinstance(actor, User) and db_only == False:
# db_only causes the return of only the stored permissions
# and not the perceived permissions for an actor
if actor.is_superuser or actor.is_staff:
return True
actor = AnonymousUserSingleton.objects.passthru_check(actor)
try:
self.model.objects.get(
permission=permission.get_stored_permission(),
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(obj),
object_id=obj.pk
)
except self.model.DoesNotExist:
# If not check if the actor's memberships is one of
# the access's holder?
roles = RoleMember.objects.get_roles_for_member(actor)
if isinstance(actor, User):
groups = actor.groups.all()
else:
groups = []
for membership in list(set(roles) | set(groups)):
if self.has_access(permission, membership, obj, db_only):
return True
logger.debug('Fallthru')
return False
else:
return True
def check_access(self, permission, actor, obj):
# TODO: Merge with has_access
obj = get_source_object(obj)
actor = get_source_object(actor)
if self.has_access(permission, actor, obj):
return True
else:
raise PermissionDenied(ugettext(u'Insufficient access.'))
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 = get_source_object(obj)
actor = get_source_object(actor)
for permission in permission_list:
if self.has_access(permission, actor, obj):
return True
raise PermissionDenied(ugettext(u'Insufficient access.'))
def get_allowed_class_objects(self, permission, actor, cls, related=None):
logger.debug('related: %s' % related)
actor = AnonymousUserSingleton.objects.passthru_check(actor)
actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(cls)
# Calculate actor role membership ACL query
total_queries = None
for role in RoleMember.objects.get_roles_for_member(actor):
role_type = ContentType.objects.get_for_model(role)
if related:
query = Q(holder_type=role_type, holder_id=role.pk, permission=permission.get_stored_permission)
else:
query = Q(holder_type=role_type, holder_id=role.pk, content_type=content_type, permission=permission.get_stored_permission)
if total_queries is None:
total_queries = query
else:
total_queries = total_queries | query
# Calculate actor group membership ACL query
if isinstance(actor, User):
groups = actor.groups.all()
else:
groups = []
for group in groups:
group_type = ContentType.objects.get_for_model(group)
if related:
query = Q(holder_type=group_type, holder_id=group.pk, permission=permission.get_stored_permission)
else:
query = Q(holder_type=group_type, holder_id=group.pk, content_type=content_type, permission=permission.get_stored_permission)
if total_queries is None:
total_queries = query
else:
total_queries = total_queries | query
if related:
actor_query = Q(holder_type=actor_type, holder_id=actor.pk, permission=permission.get_stored_permission)
master_list = [obj.content_object for obj in self.model.objects.select_related().filter(actor_query | total_queries)]
logger.debug('master_list: %s' % master_list)
# TODO: update to use Q objects and check performance diff
# kwargs = {'%s__in' % related: master_list}
# Q(**kwargs)
return (obj for obj in cls.objects.all() if getattr(obj, related) in master_list)
else:
actor_query = Q(holder_type=actor_type, holder_id=actor.pk, content_type=content_type, permission=permission.get_stored_permission)
return (obj.content_object for obj in self.model.objects.filter(actor_query | total_queries))
def get_acl_url(self, obj):
content_type = ContentType.objects.get_for_model(obj)
return reverse('acl_list', args=[content_type.app_label, content_type.model, obj.pk])
def get_new_holder_url(self, 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])
def get_holders_for(self, obj):
content_type = ContentType.objects.get_for_model(obj)
holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type, object_id=obj.pk):
if access_entry.holder_object:
# Don't add references to non existant content type objects
entry = AccessHolder.encapsulate(access_entry.holder_object)
if entry not in holder_list:
holder_list.append(entry)
return holder_list
def get_holder_permissions_for(self, obj, actor, db_only=False):
"""
Returns a list of actors that hold at least one permission for
a specific object
"""
logger.debug('obj: %s' % obj)
logger.debug('actor: %s' % actor)
if isinstance(actor, User) and db_only == False:
if actor.is_superuser or actor.is_staff:
return Permission.objects.all()
actor_type = ContentType.objects.get_for_model(actor)
content_type = ContentType.objects.get_for_model(obj)
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):
"""
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('object_list: %s' % object_list)
if isinstance(actor, User):
if actor.is_superuser or actor.is_staff:
return object_list
try:
if object_list.count() == 0:
return object_list
except TypeError:
# object_list is not a queryset
if len(object_list) == 0:
return object_list
try:
# 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)])
logger.debug('qs: %s' % qs)
if qs.count() == 0 and exception_on_empty == True:
raise PermissionDenied
return qs
except AttributeError:
# Fallback to a filtered list
object_list = list(set(object_list) & set(self.get_allowed_class_objects(permission, actor, object_list[0].__class__, related)))
logger.debug('object_list: %s' % object_list)
if len(object_list) == 0 and exception_on_empty == True:
raise PermissionDenied
return object_list
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):
cls = get_source_object(cls)
content_type = ContentType.objects.get_for_model(cls)
holder_list = []
for access_entry in self.model.objects.filter(content_type=content_type):
if access_entry.holder_object:
# Don't add references to non existant content type objects
entry = ClassAccessHolder.encapsulate(access_entry.holder_object)
if entry not in holder_list:
holder_list.append(entry)
return holder_list
def has_access(self, permission, actor, cls):
if isinstance(actor, User):
if actor.is_superuser or actor.is_staff:
return True
try:
self.model.objects.get(
permission=permission.get_stored_permission(),
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
except self.model.DoesNotExist:
return False
else:
return True
def grant(self, permission, actor, cls):
"""
Grant a permission (what), (to) an actor, (on) a specific class
"""
access_entry, created = self.model.objects.get_or_create(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
return created
def revoke(self, permission, actor, cls):
"""
Revoke a permission (what), (from) an actor, (on) a specific class
"""
try:
access_entry = self.model.objects.get(
permission=permission,
holder_type=ContentType.objects.get_for_model(actor),
holder_id=actor.pk,
content_type=ContentType.objects.get_for_model(cls),
)
access_entry.delete()
return True
except self.model.DoesNotExist:
return False
def get_holder_permissions_for(self, cls, actor):
if isinstance(actor, User):
if actor.is_superuser or actor.is_staff:
return Permission.objects.all()
actor_type = ContentType.objects.get_for_model(actor)
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)]

112
apps/acls/models.py Normal file
View File

@@ -0,0 +1,112 @@
from __future__ import absolute_import
import logging
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from permissions.models import StoredPermission
from common.models import Singleton, SingletonManager
from .managers import AccessEntryManager, DefaultAccessEntryManager
from .classes import AccessObjectClass
from .api import get_classes
logger = logging.getLogger(__name__)
class AccessEntry(models.Model):
"""
Model that hold the permission, object, actor relationship
"""
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey(
ContentType,
related_name='access_holder',
limit_choices_to={'model__in': ('user', 'group', 'role')}
)
holder_id = models.PositiveIntegerField()
holder_object = generic.GenericForeignKey(
ct_field='holder_type',
fk_field='holder_id'
)
content_type = models.ForeignKey(
ContentType,
related_name='object_content_type'
)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey(
ct_field='content_type',
fk_field='object_id'
)
objects = AccessEntryManager()
class Meta:
verbose_name = _(u'access entry')
verbose_name_plural = _(u'access entries')
def __unicode__(self):
return u'%s: %s' % (self.content_type, self.content_object)
class DefaultAccessEntry(models.Model):
"""
Model that holds the permission, class, actor relationship, that will
be added upon the creation of an instance of said class
"""
@classmethod
def get_classes(cls):
return [AccessObjectClass.encapsulate(cls) for cls in get_classes()]
permission = models.ForeignKey(StoredPermission, verbose_name=_(u'permission'))
holder_type = models.ForeignKey(
ContentType,
limit_choices_to={'model__in': ('user', 'group', 'role')},
related_name='default_access_entry_holder'
)
holder_id = models.PositiveIntegerField()
holder_object = generic.GenericForeignKey(
ct_field='holder_type',
fk_field='holder_id'
)
content_type = models.ForeignKey(
ContentType,
related_name='default_access_entry_class'
)
objects = DefaultAccessEntryManager()
class Meta:
verbose_name = _(u'default access entry')
verbose_name_plural = _(u'default access entries')
def __unicode__(self):
return u'%s: %s' % (self.content_type, self.content_object)
class CreatorSingletonManager(SingletonManager):
def passthru_check(self, holder, creator=None):
if isinstance(holder, self.model):
# TODO: raise explicit error if is instance and creator=None
return creator
else:
return holder
class CreatorSingleton(Singleton):
objects = CreatorSingletonManager()
def __unicode__(self):
return ugettext('Creator')
class Meta:
verbose_name = _(u'creator')
verbose_name_plural = _(u'creator')

14
apps/acls/permissions.py Normal file
View File

@@ -0,0 +1,14 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from permissions.models import PermissionNamespace, Permission
acls_namespace = PermissionNamespace('acls', _(u'Access control lists'))
acls_setup_namespace = PermissionNamespace('acls_setup', _(u'Access control lists'))
ACLS_EDIT_ACL = Permission.objects.register(acls_namespace, 'acl_edit', _(u'Edit ACLs'))
ACLS_VIEW_ACL = Permission.objects.register(acls_namespace, 'acl_view', _(u'View ACLs'))
ACLS_CLASS_EDIT_ACL = Permission.objects.register(acls_setup_namespace, 'acl_class_edit', _(u'Edit class default ACLs'))
ACLS_CLASS_VIEW_ACL = Permission.objects.register(acls_setup_namespace, 'acl_class_view', _(u'View class default ACLs'))

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,71 @@
import logging
from django.core.exceptions import PermissionDenied
from django.template import (TemplateSyntaxError, Library,
Node, Variable, VariableDoesNotExist)
from acls.models import AccessEntry
register = Library()
logger = logging.getLogger(__name__)
class CheckAccessNode(Node):
def __init__(self, permission_list=None, requester=None, obj=None, *args, **kwargs):
self.requester = requester
self.permission_list = permission_list
self.obj = obj
def render(self, context):
permission_list = Variable(self.permission_list).resolve(context)
logger.debug('permission_list: %s' % u','.join([unicode(p) for p in permission_list]))
try:
# Check access_object, useful for document_page views
obj = Variable('access_object').resolve(context)
logger.debug('access_object: %s' % obj)
except VariableDoesNotExist:
try:
obj = Variable(self.obj).resolve(context)
logger.debug('obj: %s' % obj)
except VariableDoesNotExist:
context[u'access'] = False
logger.debug('no obj, access False')
return u''
if not permission_list:
# There is no permissions list to check against which means
# this link is available for all
context[u'access'] = True
return u''
requester = Variable(self.requester).resolve(context)
logger.debug('requester: %s' % requester)
if obj:
try:
AccessEntry.objects.check_accesses(permission_list, requester, obj)
except PermissionDenied:
context[u'access'] = False
logger.debug('access: False')
return u''
else:
context[u'access'] = True
logger.debug('access: True')
return u''
else:
context[u'access'] = False
logger.debug('No object, access: False')
return u''
@register.tag
def check_access(parser, token):
try:
# Splitting by None == splitting by spaces.
tag_name, args = token.contents.split(None, 1)
except ValueError:
raise TemplateSyntaxError(u'%r tag requires arguments' % token.contents.split()[0])
return CheckAccessNode(*args.split())

20
apps/acls/urls.py Normal file
View File

@@ -0,0 +1,20 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('acls.views',
url(r'^new_holder_for/(?P<app_label>[-\w]+)/(?P<model_name>[-\w]+)/(?P<object_id>\d+)/$', 'acl_new_holder_for', (), 'acl_new_holder_for'),
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'^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/revoke/$', 'acl_revoke', (), 'acl_multiple_revoke'),
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/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/multiple/grant/$', 'acl_class_multiple_grant', (), 'acl_class_multiple_grant'),
url(r'^class/multiple/revoke/$', 'acl_class_multiple_revoke', (), 'acl_class_multiple_revoke'),
)

34
apps/acls/utils.py Normal file
View File

@@ -0,0 +1,34 @@
from __future__ import absolute_import
import logging
from django.contrib.contenttypes.models import ContentType
from common.models import AnonymousUserSingleton
from .models import AccessEntry, DefaultAccessEntry, CreatorSingleton
from .classes import get_source_object
logger = logging.getLogger(__name__)
def apply_default_acls(obj, actor=None):
logger.debug('actor, init: %s' % actor)
obj = get_source_object(obj)
if actor:
actor = AnonymousUserSingleton.objects.passthru_check(actor)
content_type = ContentType.objects.get_for_model(obj)
for default_acl in DefaultAccessEntry.objects.filter(content_type=content_type):
holder = CreatorSingleton.objects.passthru_check(default_acl.holder_object, actor)
if holder:
# When the creator is admin
access_entry = AccessEntry(
permission=default_acl.permission,
holder_object=holder,
content_object=obj,
)
access_entry.save()

649
apps/acls/views.py Normal file

File diff suppressed because it is too large Load Diff

27
apps/acls/widgets.py Normal file
View File

@@ -0,0 +1,27 @@
from __future__ import absolute_import
from django.utils.safestring import mark_safe
from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase
from django.template.defaultfilters import capfirst
from .literals import CONTENT_TYPE_ICON_MAP
def content_type_icon(content_type):
return mark_safe(u'<span class="famfam active famfam-%s"></span>' % CONTENT_TYPE_ICON_MAP.get('%s.%s' % (content_type.app_label, content_type.model), 'help'))
def object_w_content_type_icon(obj):
content_type = ContentType.objects.get_for_model(obj)
ct_fullname = '%s.%s' % (content_type.app_label, content_type.name)
if isinstance(obj, ModelBase):
label = getattr(obj._meta, 'verbose_name_plural', unicode(content_type))
else:
if ct_fullname == 'auth.user':
label = obj.get_full_name()
else:
label = unicode(obj)
return mark_safe('%s<span>%s</span>' % (content_type_icon(content_type), capfirst(label)))

View File

@@ -1,14 +1,17 @@
from __future__ import absolute_import
import tempfile
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth import models as auth_models
from django.contrib.auth.management import create_superuser
from django.db.models import signals
from django.dispatch import receiver
from django.db.models.signals import post_syncdb
from navigation.api import register_links, register_top_menu
from common.conf import settings as common_settings
from common.utils import validate_path
from .conf import settings as common_settings
from .utils import validate_path
def has_usable_password(context):
@@ -21,42 +24,38 @@ current_user_edit = {'text': _(u'edit details'), 'view': 'current_user_edit', 'f
register_links(['current_user_details', 'current_user_edit', 'password_change_view'], [current_user_details, current_user_edit, password_change_view], menu_name='secondary_menu')
about_view = {'text': _('about'), 'view': 'about_view', 'famfam': 'information'}
changelog_view = {'text': _('changelog'), 'view': 'changelog_view', 'famfam': 'book_open'}
license_view = {'text': _('license'), 'view': 'license_view', 'famfam': 'script'}
register_links(['about_view', 'changelog_view', 'license_view'], [about_view, changelog_view, license_view], menu_name='secondary_menu')
register_links(['about_view', 'license_view'], [about_view, license_view], menu_name='secondary_menu')
register_top_menu('about', link={'text': _(u'about'), 'view': 'about_view', 'famfam': 'information'}, position=-1)
if common_settings.AUTO_CREATE_ADMIN:
# From https://github.com/lambdalisue/django-qwert/blob/master/qwert/autoscript/__init__.py
# From http://stackoverflow.com/questions/1466827/ --
#
# Prevent interactive question about wanting a superuser created. (This code
# has to go in this otherwise empty "models" module so that it gets processed by
# the "syncdb" command during database creation.)
#
# Create our own test user automatically.
@receiver(post_syncdb, dispatch_uid='create_superuser', sender=auth_models)
def create_superuser(sender, **kwargs):
"""
From https://github.com/lambdalisue/django-qwert/blob/master/qwert/autoscript/__init__.py
From http://stackoverflow.com/questions/1466827/ --
def create_testuser(app, created_models, verbosity, **kwargs):
Prevent interactive question about wanting a superuser created. (This code
has to go in this otherwise empty "models" module so that it gets processed by
the "syncdb" command during database creation.)
Create our own admin super user automatically.
"""
if common_settings.AUTO_CREATE_ADMIN:
USERNAME = common_settings.AUTO_ADMIN_USERNAME
PASSWORD = common_settings.AUTO_ADMIN_PASSWORD
try:
auth_models.User.objects.get(username=USERNAME)
except auth_models.User.DoesNotExist:
print '*' * 80
print 'Creating test user -- login: %s, password: %s' % (USERNAME, PASSWORD)
print 'Creating super admin user -- login: %s, password: %s' % (USERNAME, PASSWORD)
print '*' * 80
assert auth_models.User.objects.create_superuser(USERNAME, 'x@x.com', PASSWORD)
else:
print 'Test user already exists. -- login: %s, password: %s' % (USERNAME, PASSWORD)
signals.post_syncdb.disconnect(
create_superuser,
sender=auth_models,
dispatch_uid='django.contrib.auth.management.create_superuser')
signals.post_syncdb.connect(create_testuser,
sender=auth_models, dispatch_uid='common.models.create_testuser')
print 'Super admin user already exists. -- login: %s, password: %s' % (USERNAME, PASSWORD)
if (validate_path(common_settings.TEMPORARY_DIRECTORY) == False) or (not common_settings.TEMPORARY_DIRECTORY):
setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp())

View File

@@ -0,0 +1,84 @@
import zipfile
try:
import zlib
COMPRESSION = zipfile.ZIP_DEFLATED
except:
COMPRESSION = zipfile.ZIP_STORED
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
class NotACompressedFile(Exception):
pass
class CompressedFile(object):
def __init__(self, file_input=None):
if file_input:
self._open(file_input)
else:
self._create()
def _create(self):
self.descriptor = StringIO()
self.zf = zipfile.ZipFile(self.descriptor, mode='w')
def _open(self, file_input):
try:
# Is it a file like object?
file_input.seek(0)
except AttributeError:
# If not, try open it.
self.descriptor = open(file_input, 'r+b')
else:
self.descriptor = file_input
try:
test = zipfile.ZipFile(self.descriptor, mode='r')
except zipfile.BadZipfile:
raise NotACompressedFile
else:
test.close()
self.descriptor.seek(0)
self.zf = zipfile.ZipFile(self.descriptor, mode='a')
def add_file(self, file_input, arcname=None):
try:
# Is it a file like object?
file_input.seek(0)
except AttributeError:
# If not, keep it
self.zf.write(file_input, arcname=arcname, compress_type=COMPRESSION)
else:
self.zf.writestr(arcname, file_input.read())
def contents(self):
return [filename for filename in self.zf.namelist() if not filename.endswith('/')]
def get_content(self, filename):
return self.zf.read(filename)
def write(self, filename=None):
# fix for Linux zip files read in Windows
for file in self.zf.filelist:
file.create_system = 0
self.descriptor.seek(0)
if filename:
descriptor = open(filename, 'w')
descriptor.write(self.descriptor.read())
else:
return self.descriptor
def as_file(self, filename):
return SimpleUploadedFile(name=filename, content=self.write().read())
def close(self):
self.zf.close()

View File

@@ -64,3 +64,12 @@ register_setting(
default=u'username',
description=_(u'Controls the mechanism used to authenticated user. Options are: username, email'),
)
register_setting(
namespace=u'common',
module=u'common.conf.settings',
name=u'ALLOW_ANONYMOUS_ACCESS',
global_name=u'COMMON_ALLOW_ANONYMOUS_ACCESS',
default=False,
description=_(u'Allow non authenticated users, access to all views'),
)

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
import os
from django import forms
@@ -8,9 +10,9 @@ from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import authenticate
from django.conf import settings
from common.utils import return_attrib
from common.widgets import DetailSelectMultiple, PlainWidget, \
TextAreaDiv, EmailInput
from .utils import return_attrib
from .widgets import (DetailSelectMultiple, PlainWidget, TextAreaDiv,
EmailInput)
class DetailForm(forms.ModelForm):
@@ -120,7 +122,7 @@ class UserForm(forms.ModelForm):
"""
class Meta:
model = User
fields = ('first_name', 'last_name')
fields = ('username', 'first_name', 'last_name', 'email')
class EmailAuthenticationForm(AuthenticationForm):
@@ -129,7 +131,7 @@ class EmailAuthenticationForm(AuthenticationForm):
authentication
"""
email = forms.CharField(label=_(u'Email'), max_length=75,
widget=EmailInput()
widget=EmailInput(attrs={'style': 'width: 100%;'})
)
def clean(self):
@@ -151,7 +153,7 @@ EmailAuthenticationForm.base_fields.keyOrder = ['email', 'password']
class FileDisplayForm(forms.Form):
text = forms.CharField(
label='',#_(u'Text'),
label='', # _(u'Text'),
widget=forms.widgets.Textarea(
attrs={'cols': 40, 'rows': 20, 'readonly': 'readonly'}
)
@@ -159,17 +161,12 @@ class FileDisplayForm(forms.Form):
def __init__(self, *args, **kwargs):
super(FileDisplayForm, self).__init__(*args, **kwargs)
changelog_path = os.path.join(settings.PROJECT_ROOT, self.DIRECTORY, self.FILENAME)
changelog_path = os.path.join(settings.PROJECT_ROOT, os.sep.join(self.DIRECTORY), self.FILENAME)
fd = open(changelog_path)
self.fields['text'].initial = fd.read()
fd.close()
class ChangelogForm(FileDisplayForm):
FILENAME = u'changelog.rst'
DIRECTORY = u'docs'
class LicenseForm(FileDisplayForm):
FILENAME = u'LICENSE'
DIRECTORY = u'docs'
DIRECTORY = [u'docs', u'credits']

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,45 +17,41 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: __init__.py:17
#: __init__.py:20
msgid "change password"
msgstr ""
#: __init__.py:18
#: __init__.py:21
msgid "user details"
msgstr ""
#: __init__.py:19
#: __init__.py:22
msgid "edit details"
msgstr ""
#: __init__.py:23 __init__.py:29
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr ""
#: __init__.py:24
msgid "changelog"
msgstr ""
#: __init__.py:25
#: __init__.py:27
msgid "license"
msgstr ""
#: forms.py:99
#: forms.py:101
msgid "Selection"
msgstr ""
#: forms.py:131
#: forms.py:133
msgid "Email"
msgstr ""
#: forms.py:142
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
msgstr ""
#: forms.py:144
#: forms.py:146
msgid "This account is inactive."
msgstr ""
@@ -99,68 +95,79 @@ msgstr ""
msgid "Landscape"
msgstr ""
#: utils.py:291
#: models.py:16
msgid "lock field"
msgstr ""
#: models.py:43
msgid "Anonymous user"
msgstr ""
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr ""
#: utils.py:295
msgid "function found"
msgstr ""
#: utils.py:293 utils.py:295
#, python-format
msgid "class found: %s"
msgstr ""
#: views.py:24 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr ""
#: views.py:41
#: views.py:36
msgid "No action selected."
msgstr ""
#: views.py:45
#: views.py:40
msgid "Must select at least one item."
msgstr ""
#: views.py:86
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr ""
#: views.py:89 views.py:106
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr ""
#: views.py:103
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr ""
#: views.py:121
#: views.py:136
msgid "Add"
msgstr ""
#: views.py:132
#: views.py:147
msgid "Remove"
msgstr ""
#: views.py:155
#: views.py:170
msgid "current user details"
msgstr ""
#: views.py:172
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr ""
#: views.py:190
msgid "Current user's details updated."
msgstr ""
#: views.py:181
#: views.py:199
msgid "edit current user details"
msgstr ""
#: views.py:207
msgid "Changelog"
#: views.py:230
msgid "License"
msgstr ""
#: views.py:220
msgid "License"
#: views.py:239
msgid "Current user password change"
msgstr ""
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr ""
#: widgets.py:58
@@ -180,6 +187,10 @@ msgid ""
"email"
msgstr ""
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr ""
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
msgstr ""
@@ -260,28 +271,32 @@ msgid "No"
msgstr ""
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:52
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr ""
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr ""
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr ""
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr ""
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"

View File

@@ -3,14 +3,14 @@
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2011.
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2011, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"PO-Revision-Date: 2011-11-04 00:58+0000\n"
"Last-Translator: rosarior <roberto.rosario.gonzalez@gmail.com>\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:39+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/"
"mayan-edms/team/es/)\n"
"Language: es\n"
@@ -19,39 +19,35 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:17
#: __init__.py:20
msgid "change password"
msgstr "cambiar contraseña"
#: __init__.py:18
#: __init__.py:21
msgid "user details"
msgstr "detalles de usuario"
#: __init__.py:19
#: __init__.py:22
msgid "edit details"
msgstr "editar detalles"
#: __init__.py:23 __init__.py:29
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr "sobre"
#: __init__.py:24
msgid "changelog"
msgstr "cambios"
#: __init__.py:25
#: __init__.py:27
msgid "license"
msgstr "licencia"
#: forms.py:99
#: forms.py:101
msgid "Selection"
msgstr "Selección"
#: forms.py:131
#: forms.py:133
msgid "Email"
msgstr "E-mail"
#: forms.py:142
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
@@ -60,7 +56,7 @@ msgstr ""
"correctas. Tenga en cuenta que los campos de contraseña distingue entre "
"mayúsculas y minúsculas."
#: forms.py:144
#: forms.py:146
msgid "This account is inactive."
msgstr "Esta cuenta está inactiva."
@@ -104,70 +100,83 @@ msgstr "Retrato"
msgid "Landscape"
msgstr "Paisaje"
#: utils.py:291
#: models.py:16
msgid "lock field"
msgstr "campo de bloqueo"
#: models.py:43
msgid "Anonymous user"
msgstr "Usuario anónimo"
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr "usuario anónimo"
#: utils.py:295
msgid "function found"
msgstr "función encontrada"
#: utils.py:293 utils.py:295
#, python-format
msgid "class found: %s"
msgstr "clase encontrada: %s"
#: views.py:24 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Su contraseña se ha modificado correctamente."
#: views.py:41
#: views.py:36
msgid "No action selected."
msgstr "Ninguna acción seleccionada."
#: views.py:45
#: views.py:40
msgid "Must select at least one item."
msgstr "Debe seleccionar al menos un artículo."
#: views.py:86
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr "Se agrego exitosamente %(selection)s a %(right_list_title)s."
#: views.py:89 views.py:106
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr "No se puede agregar %(selection)s a %(right_list_title)s."
#: views.py:103
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr "Se removió exitosamente %(selection)s de %(right_list_title)s."
#: views.py:121
#: views.py:136
msgid "Add"
msgstr "Agregar"
#: views.py:132
#: views.py:147
msgid "Remove"
msgstr "Remover"
#: views.py:155
#: views.py:170
msgid "current user details"
msgstr "detalles del usuario corriente"
#: views.py:172
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr ""
"Conflicto de correo electrónica, otro usuario tiene ese mismo correo "
"electrónico."
#: views.py:190
msgid "Current user's details updated."
msgstr "Datos del usuario corriente actualizados."
#: views.py:181
#: views.py:199
msgid "edit current user details"
msgstr "editar detalles del usuario corriente"
#: views.py:207
msgid "Changelog"
msgstr "Cambios"
#: views.py:220
#: views.py:230
msgid "License"
msgstr "Licencia"
#: views.py:239
msgid "Current user password change"
msgstr "Cambio de contraseña de usuario actual"
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Su contraseña se ha modificado correctamente."
#: widgets.py:58
msgid "None"
msgstr "Ninguno"
@@ -190,6 +199,11 @@ msgstr ""
"Controla el mecanismo utilizado para el usuario autenticado. Las opciones "
"son: 'username' nombre de usuario, 'email' correo electrónico"
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr ""
"Permita a los usuarios no autenticados, el acceso a todas las pantallas"
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
msgstr "Permisos insuficientes"
@@ -270,28 +284,32 @@ msgid "No"
msgstr "No"
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:52
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr "requerido"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr "Guardar"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr "Enviar"
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr "Cancelar"
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"
@@ -330,6 +348,3 @@ msgstr "Iniciar sesión"
#: templates/password_change_form.html:5
msgid "Password change"
msgstr "Cambio de contraseña"
#~ msgid "Cancel"
#~ msgstr "Cancelar"

Binary file not shown.

View File

@@ -0,0 +1,337 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# <pierpaolo.baldan@gmail.com>, 2011.
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-21 16:35+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/language/it/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: it\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:20
msgid "change password"
msgstr "cambia password"
#: __init__.py:21
msgid "user details"
msgstr "dettaglio utente"
#: __init__.py:22
msgid "edit details"
msgstr "modifica dettagli"
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr "a rigurdo"
#: __init__.py:27
msgid "license"
msgstr "licenza"
#: forms.py:101
msgid "Selection"
msgstr "Selezione"
#: forms.py:133
msgid "Email"
msgstr "Email"
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
msgstr "Inserisci un'indirizzo mail valido e una password. Ricorda che il campo password è case-sensitive"
#: forms.py:146
msgid "This account is inactive."
msgstr "Questo account è inattivo"
#: literals.py:24
msgid "A5"
msgstr "A5"
#: literals.py:25
msgid "A4"
msgstr "A4"
#: literals.py:26
msgid "A3"
msgstr "A3"
#: literals.py:27
msgid "B5"
msgstr "B5"
#: literals.py:28
msgid "B4"
msgstr "B4"
#: literals.py:29
msgid "Letter"
msgstr "Letter"
#: literals.py:30
msgid "Legal"
msgstr "Legal"
#: literals.py:31
msgid "Ledger"
msgstr "Mastro"
#: literals.py:38
msgid "Portrait"
msgstr "Verticale"
#: literals.py:39
msgid "Landscape"
msgstr "Orizontale"
#: models.py:16
msgid "lock field"
msgstr ""
#: models.py:43
msgid "Anonymous user"
msgstr "Utente anonimo"
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr "utente anonimo"
#: utils.py:295
msgid "function found"
msgstr "trovata funzione"
#: views.py:36
msgid "No action selected."
msgstr "Nessuna azione selezionata"
#: views.py:40
msgid "Must select at least one item."
msgstr "Devi selezionare un item"
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr "%(selection)s aggiunto con successo a %(right_list_title)s."
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr "Impossibile aggiungere %(selection)s a %(right_list_title)s."
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr "%(selection)s aggiunto correttamente rimosso dal %(right_list_title)s."
#: views.py:136
msgid "Add"
msgstr "Aggiungi"
#: views.py:147
msgid "Remove"
msgstr "Rimuovi"
#: views.py:170
msgid "current user details"
msgstr "dettagli dell'utente corrente"
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr "E-mail conflitto, un altro utente ha quella stessa email."
#: views.py:190
msgid "Current user's details updated."
msgstr "Dettagli dell'utente corrente aggiornati"
#: views.py:199
msgid "edit current user details"
msgstr "modifica i dettagli dell'utente corrente"
#: views.py:230
msgid "License"
msgstr "Licenza"
#: views.py:239
msgid "Current user password change"
msgstr "Modifica della password dell'utente corrente"
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "La tua password è stata cambiata con successo"
#: widgets.py:58
msgid "None"
msgstr "Nessuno"
#: conf/settings.py:15
msgid ""
"Temporary directory used site wide to store thumbnails, previews and "
"temporary files. If none is specified, one will be created using "
"tempfile.mkdtemp()"
msgstr "Directory temporanea utilizzata a livello di sito per thumbnails, anteprime e file temporanei. Se non viene specificato, ne verrà creata utilizzando tempfile.mkdtemp()"
#: conf/settings.py:65
msgid ""
"Controls the mechanism used to authenticated user. Options are: username, "
"email"
msgstr "Controllo del meccanismo di autenticazione. Le opzioni possibili sono:username,email"
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr "Consentire agli utenti non autenticati, l'accesso a tutte le viste"
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
msgstr "Permessi insufficienti"
#: templates/403.html:9
msgid "You don't have enough permissions for this operation."
msgstr "Non hai i permessi per effettuare questa operazione."
#: templates/404.html:3 templates/404.html.py:7
msgid "Page not found"
msgstr "Pagina non trovata"
#: templates/404.html:9
msgid "Sorry, but the requested page could not be found."
msgstr "Scusa ma la pagina richiesta non è disponibile"
#: templates/calculate_form_title.html:11
#, python-format
msgid "Details for %(object_name)s: %(object)s"
msgstr "Dettagli per %(object_name)s: %(object)s"
#: templates/calculate_form_title.html:13
#, python-format
msgid "Details for: %(object)s"
msgstr "Detaglio per: %(object)s"
#: templates/calculate_form_title.html:18
#, python-format
msgid "Edit %(object_name)s:"
msgstr "Modifica %(object_name)s:"
#: templates/calculate_form_title.html:20
msgid "Edit"
msgstr "Modifica"
#: templates/calculate_form_title.html:24
#, python-format
msgid "Create new %(object_name)s"
msgstr "Crea nuovo %(object_name)s"
#: templates/calculate_form_title.html:26
msgid "Create"
msgstr "Crea"
#: templates/generic_assign_remove.html:3
#, python-format
msgid "Assign %(title)s %(object)s"
msgstr "Assigna %(title)s %(object)s"
#: templates/generic_confirm.html:3 templates/generic_confirm.html.py:18
msgid "Confirm"
msgstr "Conferma"
#: templates/generic_confirm.html:16
msgid "Confirm delete"
msgstr "Conferma la cancellazione"
#: templates/generic_confirm.html:32
msgid "form icon"
msgstr "icona del modulo"
#: templates/generic_confirm.html:40
#, python-format
msgid "Are you sure you wish to delete %(object_name)s: %(object)s?"
msgstr "Sei sicuro di voler cancellare %(object_name)s: %(object)s?"
#: templates/generic_confirm.html:42
#, python-format
msgid "Are you sure you wish to delete: %(object)s?"
msgstr "Sei sicuro di volr cancellare: %(object)s?"
#: templates/generic_confirm.html:50
msgid "Yes"
msgstr "Si"
#: templates/generic_confirm.html:54
msgid "No"
msgstr "No"
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr "richiesto"
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr "Salva"
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr "Sottometti"
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr "Annullare"
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"
msgstr "Lista di %(stripped_title)s"
#: templates/generic_list_horizontal_subtemplate.html:23
#: templates/generic_list_subtemplate.html:24
#, python-format
msgid ""
"List of %(title)s (%(start)s - %(end)s out of %(total)s) (Page "
"%(page_number)s of %(total_pages)s)"
msgstr "Lista di %(title)s (%(start)s - %(end)s fuori %(total)s) (Page %(page_number)s of %(total_pages)s)"
#: templates/generic_list_horizontal_subtemplate.html:25
#: templates/generic_list_subtemplate.html:26
#, python-format
msgid "List of %(title)s (%(total)s)"
msgstr "Lista di %(title)s (%(total)s)"
#: templates/generic_list_subtemplate.html:72
msgid "Identifier"
msgstr "Identificatore"
#: templates/generic_list_subtemplate.html:152
#, python-format
msgid "There are no %(stripped_title)s"
msgstr "Non ci sono %(stripped_title)s"
#: templates/login.html:5
msgid "Login"
msgstr "Login"
#: templates/password_change_done.html:3 templates/password_change_form.html:3
#: templates/password_change_form.html:5
msgid "Password change"
msgstr "Cambia password"

Binary file not shown.

View File

@@ -0,0 +1,339 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# mic, 2012.
# mic <diveaway12@gmail.com>, 2012.
# <winterfall24@gmail.com>, 2012.
# <winterfall24@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-21 15:17+0000\n"
"Last-Translator: mic <winterfall24@gmail.com>\n"
"Language-Team: Polish (http://www.transifex.net/projects/p/mayan-edms/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:20
msgid "change password"
msgstr "zmień hasło"
#: __init__.py:21
msgid "user details"
msgstr "szczegóły konta użytkownika"
#: __init__.py:22
msgid "edit details"
msgstr "edytuj szczegóły"
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr "informacje o"
#: __init__.py:27
msgid "license"
msgstr "licencja"
#: forms.py:101
msgid "Selection"
msgstr "Zaznaczenie"
#: forms.py:133
msgid "Email"
msgstr "E-mail"
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
msgstr "Proszę wpisać poprawną nazwę użytkownika i hasło. Uwaga: wielkość liter ma znaczenie."
#: forms.py:146
msgid "This account is inactive."
msgstr "To konto jest nieaktywne."
#: literals.py:24
msgid "A5"
msgstr "A5"
#: literals.py:25
msgid "A4"
msgstr "A4"
#: literals.py:26
msgid "A3"
msgstr "A3"
#: literals.py:27
msgid "B5"
msgstr "B5"
#: literals.py:28
msgid "B4"
msgstr "B4"
#: literals.py:29
msgid "Letter"
msgstr "Letter"
#: literals.py:30
msgid "Legal"
msgstr "Legal"
#: literals.py:31
msgid "Ledger"
msgstr "Ledger"
#: literals.py:38
msgid "Portrait"
msgstr "Portrait"
#: literals.py:39
msgid "Landscape"
msgstr "Landscape"
#: models.py:16
msgid "lock field"
msgstr "zablokować pole"
#: models.py:43
msgid "Anonymous user"
msgstr "Użytkownik anonimowy"
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr "użytkownik anonimowy"
#: utils.py:295
msgid "function found"
msgstr "znaleźć funkcję"
#: views.py:36
msgid "No action selected."
msgstr "Nie wybrano żadnego działania"
#: views.py:40
msgid "Must select at least one item."
msgstr "Musisz wybrać co najmniej jeden element."
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr " %(selection)s pomyślnie dodana do %(right_list_title)s."
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr "Nie można dodać %(selection)s do %(right_list_title)s."
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr " %(selection)s pomyślnie dodana usunięty z %(right_list_title)s."
#: views.py:136
msgid "Add"
msgstr "Dodaj"
#: views.py:147
msgid "Remove"
msgstr "Usuń"
#: views.py:170
msgid "current user details"
msgstr "aktualne dane użytkownika"
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr "Użytkownik o podanym adresie e-mail już istnieje."
#: views.py:190
msgid "Current user's details updated."
msgstr "Aktualne dane użytkownika aktualizowane."
#: views.py:199
msgid "edit current user details"
msgstr "edytuj aktualne dane użytkownika"
#: views.py:230
msgid "License"
msgstr "Licencja"
#: views.py:239
msgid "Current user password change"
msgstr "Zmiana hasła użytkownika"
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Twoje hasło zostało pomyślnie zmienione."
#: widgets.py:58
msgid "None"
msgstr "Brak"
#: conf/settings.py:15
msgid ""
"Temporary directory used site wide to store thumbnails, previews and "
"temporary files. If none is specified, one will be created using "
"tempfile.mkdtemp()"
msgstr "Katalog tymczasowy używany do przechowywania całej witryny, miniatur, podglądów i plików tymczasowych. Jeśli nie zostanie określony, zostanie utworzony za pomocą tempfile.mkdtemp ()"
#: conf/settings.py:65
msgid ""
"Controls the mechanism used to authenticated user. Options are: username, "
"email"
msgstr ""
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr ""
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
msgstr "Niewystarczające uprawnienia"
#: templates/403.html:9
msgid "You don't have enough permissions for this operation."
msgstr "Nie masz wystarczających uprawnień do tej operacji."
#: templates/404.html:3 templates/404.html.py:7
msgid "Page not found"
msgstr "Nie znaleziono strony"
#: templates/404.html:9
msgid "Sorry, but the requested page could not be found."
msgstr "Przykro nam, ale żądana strona nie została odnaleziona."
#: templates/calculate_form_title.html:11
#, python-format
msgid "Details for %(object_name)s: %(object)s"
msgstr "Szczegóły dla %(object_name)s : %(object)s "
#: templates/calculate_form_title.html:13
#, python-format
msgid "Details for: %(object)s"
msgstr "Szczegóły: %(object)s "
#: templates/calculate_form_title.html:18
#, python-format
msgid "Edit %(object_name)s:"
msgstr "Edytuj %(object_name)s :"
#: templates/calculate_form_title.html:20
msgid "Edit"
msgstr "Edytuj"
#: templates/calculate_form_title.html:24
#, python-format
msgid "Create new %(object_name)s"
msgstr "Utwórz nową %(object_name)s "
#: templates/calculate_form_title.html:26
msgid "Create"
msgstr "Utwórz"
#: templates/generic_assign_remove.html:3
#, python-format
msgid "Assign %(title)s %(object)s"
msgstr "Przypisz %(title)s %(object)s"
#: templates/generic_confirm.html:3 templates/generic_confirm.html.py:18
msgid "Confirm"
msgstr "Potwierdź"
#: templates/generic_confirm.html:16
msgid "Confirm delete"
msgstr "Potwierdź usunięcie"
#: templates/generic_confirm.html:32
msgid "form icon"
msgstr "form icon"
#: templates/generic_confirm.html:40
#, python-format
msgid "Are you sure you wish to delete %(object_name)s: %(object)s?"
msgstr "Czy na pewno chcesz usunąć %(object_name)s : %(object)s ?"
#: templates/generic_confirm.html:42
#, python-format
msgid "Are you sure you wish to delete: %(object)s?"
msgstr "Czy na pewno chcesz usunąć: %(object)s?"
#: templates/generic_confirm.html:50
msgid "Yes"
msgstr "Tak"
#: templates/generic_confirm.html:54
msgid "No"
msgstr "Nie"
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr "wymagane"
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr "Zapisz"
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr "Wyślij"
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr "Anuluj"
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"
msgstr "Wykaz %(stripped_title)s"
#: templates/generic_list_horizontal_subtemplate.html:23
#: templates/generic_list_subtemplate.html:24
#, python-format
msgid ""
"List of %(title)s (%(start)s - %(end)s out of %(total)s) (Page "
"%(page_number)s of %(total_pages)s)"
msgstr "Wykaz %(title)s (%(start)s - %(end)s z %(total)s) (Page %(page_number)s z %(total_pages)s)"
#: templates/generic_list_horizontal_subtemplate.html:25
#: templates/generic_list_subtemplate.html:26
#, python-format
msgid "List of %(title)s (%(total)s)"
msgstr "Wykaz %(title)s (%(total)s)"
#: templates/generic_list_subtemplate.html:72
msgid "Identifier"
msgstr "Identyfikator"
#: templates/generic_list_subtemplate.html:152
#, python-format
msgid "There are no %(stripped_title)s"
msgstr "Brak %(stripped_title)s"
#: templates/login.html:5
msgid "Login"
msgstr "Zaloguj"
#: templates/password_change_done.html:3 templates/password_change_form.html:3
#: templates/password_change_form.html:5
msgid "Password change"
msgstr "Zmiana hasła"

View File

@@ -1,65 +1,59 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
#
# Translators:
# <dev.emerson@gmail.com>, 2011.
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"PO-Revision-Date: 2011-11-02 02:18+0000\n"
"Last-Translator: emersonsoares <dev.emerson@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/"
"team/pt/)\n"
"Language: pt\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-21 15:07+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/language/pt/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pt\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:17
#: __init__.py:20
msgid "change password"
msgstr "alterar a senha"
#: __init__.py:18
#: __init__.py:21
msgid "user details"
msgstr "detalhes do usuário"
#: __init__.py:19
#: __init__.py:22
msgid "edit details"
msgstr "editar detalhes"
#: __init__.py:23 __init__.py:29
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr "sobre"
#: __init__.py:24
msgid "changelog"
msgstr "log de alterações"
#: __init__.py:25
#: __init__.py:27
msgid "license"
msgstr "licença"
#: forms.py:99
#: forms.py:101
msgid "Selection"
msgstr "Seleção"
#: forms.py:131
#: forms.py:133
msgid "Email"
msgstr "E-mail"
#: forms.py:142
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
msgstr ""
"Por favor insira o e-mail e senha corretos. Note que os campos de senha são "
"case-sensitive."
msgstr "Por favor insira o e-mail e senha corretos. Note que os campos de senha são case-sensitive."
#: forms.py:144
#: forms.py:146
msgid "This account is inactive."
msgstr "Esta conta está inativa."
@@ -103,70 +97,81 @@ msgstr "Retrato"
msgid "Landscape"
msgstr "Paisagem"
#: utils.py:291
#: models.py:16
msgid "lock field"
msgstr ""
#: models.py:43
msgid "Anonymous user"
msgstr "Usuário anônimo"
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr "usuário anônimo"
#: utils.py:295
msgid "function found"
msgstr "função encontrada"
#: utils.py:293 utils.py:295
#, python-format
msgid "class found: %s"
msgstr "classe encontrada: %s"
#: views.py:24 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Sua senha foi alterada com êxito."
#: views.py:41
#: views.py:36
msgid "No action selected."
msgstr "Nenhuma ação selecionada."
#: views.py:45
#: views.py:40
msgid "Must select at least one item."
msgstr "Deve selecionar pelo menos um item."
#: views.py:86
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr "%(selection)s adicionadas com sucesso a %(right_list_title)s ."
#: views.py:89 views.py:106
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr "Não foi possível adicionar %(selection)s para %(right_list_title)s ."
#: views.py:103
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr " %(selection)s adicionado com sucesso removidos %(right_list_title)s."
#: views.py:121
#: views.py:136
msgid "Add"
msgstr "Adicionar"
#: views.py:132
#: views.py:147
msgid "Remove"
msgstr "Remover"
#: views.py:155
#: views.py:170
msgid "current user details"
msgstr "detalhes atuais do usuário"
#: views.py:172
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr "E-mail conflito, outro usuário que tem mesmo e-mail."
#: views.py:190
msgid "Current user's details updated."
msgstr "Detalhes do usuário atual atualizados."
#: views.py:181
#: views.py:199
msgid "edit current user details"
msgstr "editar os detalhes do usuário atual"
#: views.py:207
msgid "Changelog"
msgstr "Log de alterações"
#: views.py:220
#: views.py:230
msgid "License"
msgstr "Licença"
#: views.py:239
msgid "Current user password change"
msgstr "Alteração de senha do usuário atual"
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Sua senha foi alterada com êxito."
#: widgets.py:58
msgid "None"
msgstr "Nenhum"
@@ -174,20 +179,19 @@ msgstr "Nenhum"
#: conf/settings.py:15
msgid ""
"Temporary directory used site wide to store thumbnails, previews and "
"temporary files. If none is specified, one will be created using tempfile."
"mkdtemp()"
msgstr ""
"Diretório temporário usado para armazenar miniaturas, previews e arquivos "
"temporários. Se nenhum for especificado, um será criado usando tempfile."
"mkdtemp()"
"temporary files. If none is specified, one will be created using "
"tempfile.mkdtemp()"
msgstr "Diretório temporário usado para armazenar miniaturas, previews e arquivos temporários. Se nenhum for especificado, um será criado usando tempfile.mkdtemp()"
#: conf/settings.py:65
msgid ""
"Controls the mechanism used to authenticated user. Options are: username, "
"email"
msgstr "Controla o mecanismo usado para usuário autenticado. As opções são: e-mail, nome de usuário,"
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr ""
"Controla o mecanismo usado para usuário autenticado. As opções são: e-mail, "
"nome de usuário,"
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
@@ -269,28 +273,32 @@ msgid "No"
msgstr "Não"
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:52
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr "exigido"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr "Salvar"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr "Submeter"
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr "Cancelar"
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"
@@ -302,9 +310,7 @@ msgstr "Lista de %(stripped_title)s "
msgid ""
"List of %(title)s (%(start)s - %(end)s out of %(total)s) (Page "
"%(page_number)s of %(total_pages)s)"
msgstr ""
"Lista de %(title)s (%(start)s - %(end)s de %(total)s) (Page %(page_number)s "
"of %(total_pages)s)"
msgstr "Lista de %(title)s (%(start)s - %(end)s de %(total)s) (Page %(page_number)s of %(total_pages)s)"
#: templates/generic_list_horizontal_subtemplate.html:25
#: templates/generic_list_subtemplate.html:26
@@ -329,6 +335,3 @@ msgstr "Login"
#: templates/password_change_form.html:5
msgid "Password change"
msgstr "Alterar a senha"
#~ msgid "Cancel"
#~ msgstr "Cancelar"

View File

@@ -1,56 +1,54 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
#
# Translators:
# Sergey Glita <gsv70@mail.ru>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"PO-Revision-Date: 2011-11-22 19:21+0000\n"
"Last-Translator: gsv70 <gsv70@mail.ru>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/ru/)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:18+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/"
"ru/)\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:17
#: __init__.py:20
msgid "change password"
msgstr "Изменение пароля"
#: __init__.py:18
#: __init__.py:21
msgid "user details"
msgstr "сведения о пользователе"
#: __init__.py:19
#: __init__.py:22
msgid "edit details"
msgstr "изменение сведений"
#: __init__.py:23 __init__.py:29
#: __init__.py:26 __init__.py:31
msgid "about"
msgstr "инфо"
#: __init__.py:24
msgid "changelog"
msgstr "изменения"
#: __init__.py:25
#: __init__.py:27
msgid "license"
msgstr "лицензия"
#: forms.py:99
#: forms.py:101
msgid "Selection"
msgstr "Выбор"
#: forms.py:131
#: forms.py:133
msgid "Email"
msgstr "Email"
#: forms.py:142
#: forms.py:144
msgid ""
"Please enter a correct email and password. Note that the password fields is "
"case-sensitive."
@@ -58,7 +56,7 @@ msgstr ""
"Пожалуйста, введите правильный адрес электронной почты и пароль с учетом "
"регистра."
#: forms.py:144
#: forms.py:146
msgid "This account is inactive."
msgstr "Эта учетная запись неактивна."
@@ -102,70 +100,81 @@ msgstr "Портрет"
msgid "Landscape"
msgstr "Пейзаж"
#: utils.py:291
#: models.py:16
msgid "lock field"
msgstr ""
#: models.py:43
msgid "Anonymous user"
msgstr ""
#: models.py:46 models.py:47
msgid "anonymous user"
msgstr ""
#: utils.py:295
msgid "function found"
msgstr "функция найдена"
#: utils.py:293 utils.py:295
#, python-format
msgid "class found: %s"
msgstr "класс найден: %s."
#: views.py:24 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Ваш пароль был изменен."
#: views.py:41
#: views.py:36
msgid "No action selected."
msgstr "Никаких действий не выбрано."
#: views.py:45
#: views.py:40
msgid "Must select at least one item."
msgstr "Необходимо выбрать хотя бы один элемент."
#: views.py:86
#: views.py:88
#, python-format
msgid "%(selection)s added successfully added to %(right_list_title)s."
msgstr "%(selection)s успешно добавлен в %(right_list_title)s ."
#: views.py:89 views.py:106
#: views.py:94 views.py:121
#, python-format
msgid "Unable to add %(selection)s to %(right_list_title)s."
msgstr "Не удалось добавить %(selection)s до %(right_list_title)s ."
#: views.py:103
#: views.py:115
#, python-format
msgid "%(selection)s added successfully removed from %(right_list_title)s."
msgstr "%(selection)s успешно удален из %(right_list_title)s ."
#: views.py:121
#: views.py:136
msgid "Add"
msgstr "Добавить"
#: views.py:132
#: views.py:147
msgid "Remove"
msgstr "Удалить"
#: views.py:155
#: views.py:170
msgid "current user details"
msgstr "данные пользователя"
#: views.py:172
#: views.py:187
msgid "E-mail conflict, another user has that same email."
msgstr ""
#: views.py:190
msgid "Current user's details updated."
msgstr "Данные пользователя обновлены."
#: views.py:181
#: views.py:199
msgid "edit current user details"
msgstr "редактировать данные пользователя"
#: views.py:207
msgid "Changelog"
msgstr "Изменения"
#: views.py:220
#: views.py:230
msgid "License"
msgstr "Лицензия"
#: views.py:239
msgid "Current user password change"
msgstr ""
#: views.py:254 templates/password_change_done.html:5
msgid "Your password has been successfully changed."
msgstr "Ваш пароль был изменен."
#: widgets.py:58
msgid "None"
msgstr "Ни один"
@@ -173,8 +182,8 @@ msgstr "Ни один"
#: conf/settings.py:15
msgid ""
"Temporary directory used site wide to store thumbnails, previews and "
"temporary files. If none is specified, one will be created using "
"tempfile.mkdtemp()"
"temporary files. If none is specified, one will be created using tempfile."
"mkdtemp()"
msgstr ""
"Временный каталог, используемый сайтом для хранения миниатюр, превью и "
"временных файлов. Если он не указан, он будет создан с использованием "
@@ -188,6 +197,10 @@ msgstr ""
"Управление механизмом, используемым для аутентификации пользователя. "
"Возможные варианты: имя пользователя, адрес электронной почты"
#: conf/settings.py:74
msgid "Allow non authenticated users, access to all views"
msgstr ""
#: templates/403.html:3 templates/403.html.py:7
msgid "Insufficient permissions"
msgstr "Недостаточно прав"
@@ -268,28 +281,32 @@ msgid "No"
msgstr "Нет"
#: templates/generic_form_instance.html:37
#: templates/generic_form_subtemplate.html:52
#: templates/generic_form_subtemplate.html:56
msgid "required"
msgstr "требуется"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Save"
msgstr "Сохранить"
#: templates/generic_form_subtemplate.html:76
#: templates/generic_form_subtemplate.html:78
#: templates/generic_form_subtemplate.html:80
#: templates/generic_form_subtemplate.html:82
#: templates/generic_list_horizontal_subtemplate.html:51
#: templates/generic_list_horizontal_subtemplate.html:178
#: templates/generic_list_horizontal_subtemplate.html:90
#: templates/generic_list_subtemplate.html:52
#: templates/generic_list_subtemplate.html:178
msgid "Submit"
msgstr "Выполнить"
#: templates/generic_form_subtemplate.html:87
msgid "Cancel"
msgstr ""
#: templates/generic_list.html:6 templates/generic_list_horizontal.html:6
#, python-format
msgid "List of %(stripped_title)s"
@@ -302,8 +319,8 @@ msgid ""
"List of %(title)s (%(start)s - %(end)s out of %(total)s) (Page "
"%(page_number)s of %(total_pages)s)"
msgstr ""
"Список %(title)s (%(start)s - %(end)s из %(total)s) (Page %(page_number)s из"
" %(total_pages)s)"
"Список %(title)s (%(start)s - %(end)s из %(total)s) (Page %(page_number)s из "
"%(total_pages)s)"
#: templates/generic_list_horizontal_subtemplate.html:25
#: templates/generic_list_subtemplate.html:26
@@ -328,5 +345,3 @@ msgstr "Войти"
#: templates/password_change_form.html:5
msgid "Password change"
msgstr "Изменение пароля"

View File

@@ -1,8 +1,12 @@
from __future__ import absolute_import
import re
from django.http import HttpResponseRedirect
from django.conf import settings
from ..conf.settings import ALLOW_ANONYMOUS_ACCESS
EXEMPT_URLS = [re.compile(settings.LOGIN_URL.lstrip('/'))]
if hasattr(settings, 'LOGIN_EXEMPT_URLS'):
EXEMPT_URLS += [re.compile(expr) for expr in settings.LOGIN_EXEMPT_URLS]
@@ -20,13 +24,14 @@ class LoginRequiredMiddleware:
"""
def process_request(self, request):
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)
if not ALLOW_ANONYMOUS_ACCESS:
assert hasattr(request, 'user'), "The Login Required middleware\
requires authentication middleware to be installed. Edit your\
MIDDLEWARE_CLASSES setting to insert\
'django.contrib.auth.middlware.AuthenticationMiddleware'. If that doesn't\
work, ensure your TEMPLATE_CONTEXT_PROCESSORS setting includes\
'django.core.context_processors.auth'."
if not request.user.is_authenticated():
path = request.path_info.lstrip('/')
if not any(m.match(path) for m in EXEMPT_URLS):
return HttpResponseRedirect(settings.LOGIN_URL)

View File

@@ -1,3 +1,47 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.contrib.auth.models import AnonymousUser
# Create your models here.
SINGLETON_LOCK_ID = 1
class SingletonManager(models.Manager):
def get(self, **kwargs):
instance, created = self.model.objects.get_or_create(lock_id=SINGLETON_LOCK_ID, **kwargs)
return instance
class Singleton(models.Model):
lock_id = models.CharField(max_length=1, default=SINGLETON_LOCK_ID, editable=False, verbose_name=_(u'lock field'), unique=True)
objects = SingletonManager()
def save(self, *args, **kwargs):
self.id = 1
super(Singleton, self).save(*args, **kwargs)
def delete(self):
pass
class Meta:
abstract = True
class AnonymousUserSingletonManager(SingletonManager):
def passthru_check(self, user):
if isinstance(user, AnonymousUser):
return self.model.objects.get()
else:
return user
class AnonymousUserSingleton(Singleton):
objects = AnonymousUserSingletonManager()
def __unicode__(self):
return ugettext('Anonymous user')
class Meta:
verbose_name = _(u'anonymous user')
verbose_name_plural = _(u'anonymous user')

View File

@@ -35,6 +35,10 @@
<input name="next" type="hidden" value="{{ next }}" />
{% endif %}
{% if previous %}
<input name="previous" type="hidden" value="{{ previous }}" />
{% endif %}
{% for hidden_field in hidden_fields %}
{{ hidden_field.as_hidden }}
{% endfor %}
@@ -77,6 +81,13 @@
{% endif %}
{% if submit_label %}{{ submit_label }}{% else %}{% if object %}{% trans "Save" %}{% else %}{% trans "Submit" %}{% endif %}{% endif %}
</button>
{% if previous %}
<a href="#header" onclick='{% if previous %}window.location.replace("{{ previous }}");{% else %}history.go(-1);{% endif %}' class="button">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/cross.png" alt="{% if cancel_label %}{{ cancel_label }}{% else %}{% trans 'Cancel' %}{% endif %}"/> {% if cancel_label %}{{ cancel_label }}{% else %}{% trans "Cancel" %}{% endif %}
</a>
{% endif %}
{% comment %}
<a href="#header" class="button">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/cross.png" alt="{% trans 'Cancel' %}"/> {% trans 'Cancel' %}

View File

@@ -59,95 +59,7 @@
<div style="border: 1px solid; height: {{ scrollable_content_height }}; overflow: auto;">
{% endif %}
{% comment %}
<table class="table">
<tbody>
{% if not hide_header %}
<tr>
{% if multi_select or multi_select_as_buttons %}
<th class="first"><input type="checkbox" class="checkbox toggle" /></th>
{% endif %}
{% if not hide_object %}
<th>{% trans "Identifier" %}</th>
{% endif %}
{% for column in extra_columns_preffixed %}
<th>{{ column.name|capfirst }}</th>
{% endfor %}
{% for column in object_list.0|get_model_list_columns %}
<th>{{ column.name|capfirst }}</th>
{% endfor %}
{% for column in extra_columns %}
<th>{{ column.name|capfirst }}</th>
{% endfor %}
{% if not hide_links %}
<th class="">&nbsp;</th>
{% endif %}
</tr>
{% endif %}
{% for object in object_list %}
<tr class="{% cycle 'odd' 'even2' %}">
{% if multi_select or multi_select_as_buttons %}
<td><input type="checkbox" class="checkbox" name="pk_{{ object.pk }}" value="" /></td>
{% endif %}
{% if not hide_object %}
{% if main_object %}
{% with object|object_property:main_object as object %}
<td>{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}</td>
{% endwith %}
{% else %}
<td>{% if not hide_link %}<a href="{{ object.get_absolute_url }}">{{ object }}</a>{% else %}{{ object }}{% endif %}</td>
{% endif %}
{% endif %}
{% for column in extra_columns_preffixed %}
{% if column.keep_together %}
<td>
{{ object|object_property:column.attribute|make_non_breakable }}
</td>
{% else %}
<td>{{ object|object_property:column.attribute }}</td>
{% endif %}
{% endfor %}
{% if not hide_columns %}
{% for column in object|get_model_list_columns %}
<td>{{ object|object_property:column.attribute }}</td>
{% endfor %}
{% endif %}
{% for column in extra_columns %}
{% if column.keep_together %}
<td>
{{ object|object_property:column.attribute|make_non_breakable }}
</td>
{% else %}
<td>{{ object|object_property:column.attribute }}</td>
{% endif %}
{% endfor %}
{% if not hide_links %}
{% if list_object_variable_name %}
{% copy_variable object as list_object_variable_name %}
{% copy_variable list_object_variable_name as "navigation_object_name" %}
{% endif %}
<td class="last">
{% if navigation_object_links %}
{% with navigation_object_links as overrided_object_links %}
{% object_navigation_template %}
{% endwith %}
{% else %}
{% object_navigation_template %}
{% endif %}
</td>
{% endif %}
</tr>
{% empty %}
<tr><td colspan=99 class="tc">{% blocktrans with title|striptags as stripped_title %}There are no {{ stripped_title }}{% endblocktrans %}</td></tr>
{% endfor %}
</tbody>
</table>
{% endcomment %}
<div class="group navform wat-cf">
{% for object in object_list %}
{{ object }}

View File

@@ -0,0 +1,32 @@
from django import template
register = template.Library()
class SetVarNode(template.Node):
def __init__(self, var_name, var_value):
self.var_name = var_name
self.var_value = var_value
def render(self, context):
try:
value = template.Variable(self.var_value).resolve(context)
except template.VariableDoesNotExist:
value = ""
#context[self.var_name] = value
# Make it global across all blocks
context.dicts[0][self.var_name] = value
return u""
def set_var(parser, token):
"""
{% set <var_name> = <var_value> %}
"""
parts = token.split_contents()
if len(parts) < 4:
raise template.TemplateSyntaxError("'set' tag must be of the form: {% set <var_name> = <var_value> %}")
return SetVarNode(parts[1], parts[3])
register.tag('set', set_var)

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
"""}

View File

@@ -4,7 +4,6 @@ from django.conf import settings
urlpatterns = patterns('common.views',
url(r'^about/$', direct_to_template, {'template': 'about.html'}, 'about_view'),
url(r'^changelog/$', 'changelog_view', (), 'changelog_view'),
url(r'^license/$', 'license_view', (), 'license_view'),
url(r'^password/change/done/$', 'password_change_done', (), name='password_change_done'),
url(r'^object/multiple/action/$', 'multi_object_action_view', (), name='multi_object_action_view'),
@@ -13,12 +12,12 @@ urlpatterns = patterns('common.views',
url(r'^user/edit/$', 'current_user_edit', (), 'current_user_edit'),
url(r'^login/$', 'login_view', (), name='login_view'),
url(r'^password/change/$', 'password_change_view', (), name='password_change_view'),
)
urlpatterns += patterns('',
url(r'^logout/$', 'django.contrib.auth.views.logout', {'next_page': '/'}, name='logout_view'),
url(r'^password/change/$', 'django.contrib.auth.views.password_change', {'template_name': 'password_change_form.html', 'post_change_redirect': '/password/change/done/'}, name='password_change_view'),
url(r'^password/reset/$', 'django.contrib.auth.views.password_reset', {'email_template_name': 'password_reset_email.html', 'template_name': 'password_reset_form.html', 'post_reset_redirect': '/password/reset/done'}, name='password_reset_view'),
url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$', 'django.contrib.auth.views.password_reset_confirm', {'template_name': 'password_reset_confirm.html', 'post_reset_redirect': '/password/reset/complete/'}, name='password_reset_confirm_view'),
url(r'^password/reset/complete/$', 'django.contrib.auth.views.password_reset_complete', {'template_name': 'password_reset_complete.html'}, name='password_reset_complete_view'),

View File

@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import os
import re
import types
@@ -16,7 +18,7 @@ from django.contrib.auth.models import User
def urlquote(link=None, get=None):
u'''
u"""
This method does both: urlquote() and urlencode()
urlqoute(): Quote special characters in 'link'
@@ -31,7 +33,7 @@ def urlquote(link=None, get=None):
urlquote('/mypath/', {'key': 'value'}) --> '/mypath/?key=value'
urlquote('/mypath/', {'key': ['value1', 'value2']}) --> '/mypath/?key=value1&key=value2'
urlquote({'key': ['value1', 'value2']}) --> 'key=value1&key=value2'
'''
"""
if get is None:
get = []
@@ -110,7 +112,9 @@ def pretty_size_10(size):
# http://www.johncardinal.com/tmgutil/capitalizenames.htm
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)
mac = re.compile(r'^Mac(\w)(?=\w)', re.I)
suffixes = [
@@ -290,11 +294,11 @@ def return_type(value):
if isinstance(value, types.FunctionType):
return value.__doc__ if value.__doc__ else _(u'function found')
elif isinstance(value, types.ClassType):
return _(u'class found: %s') % unicode(value).split("'")[1].split('.')[-1]
return u'%s.%s' % (value.__class__.__module__, value.__class__.__name__)
elif isinstance(value, types.TypeType):
return _(u'class found: %s') % unicode(value).split("'")[1].split('.')[-1]
return u'%s.%s' % (value.__module__, value.__name__)
elif isinstance(value, types.DictType) or isinstance(value, types.DictionaryType):
return ','.join(list(value))
return u', '.join(list(value))
else:
return value
@@ -326,6 +330,24 @@ def generate_choices_w_labels(choices, display_object_type=True):
return sorted(results, key=lambda x: x[1])
def get_object_name(obj, display_object_type=True):
ct_label = ContentType.objects.get_for_model(obj).name
if isinstance(obj, User):
label = obj.get_full_name() if obj.get_full_name() else obj
else:
label = unicode(obj)
if display_object_type:
try:
verbose_name = unicode(obj._meta.verbose_name)
except AttributeError:
verbose_name = ct_label
return u'%s: %s' % (verbose_name, label)
else:
return u'%s' % (label)
def return_diff(old_obj, new_obj, attrib_list=None):
diff_dict = {}
if not attrib_list:

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from django.http import HttpResponseRedirect
@@ -9,20 +11,13 @@ from django.core.urlresolvers import reverse
from django.utils.http import urlencode
from django.contrib.auth.views import login
from django.utils.simplejson import dumps, loads
from django.contrib.auth.views import password_change
from django.contrib.auth.models import User
from django.conf import settings
from common.forms import ChoiceForm, UserForm, UserForm_view, \
ChangelogForm, LicenseForm
from common.forms import EmailAuthenticationForm
from common.conf.settings import LOGIN_METHOD
def password_change_done(request):
"""
View called when the new user password has been accepted
"""
messages.success(request, _(u'Your password has been successfully changed.'))
return redirect('home')
from .forms import (ChoiceForm, UserForm, UserForm_view, LicenseForm,
EmailAuthenticationForm)
from .conf.settings import LOGIN_METHOD
def multi_object_action_view(request):
@@ -65,7 +60,7 @@ def get_obj_from_content_type_string(string):
return ct.get_object_for_this_type(pk=pk)
def assign_remove(request, left_list, right_list, add_method, remove_method, left_list_title, right_list_title, decode_content_type=False, extra_context=None):
def assign_remove(request, left_list, right_list, add_method, remove_method, left_list_title, right_list_title, decode_content_type=False, extra_context=None, grouped=False):
left_list_name = u'left_list'
right_list_name = u'right_list'
@@ -76,7 +71,14 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
choices=left_list())
if unselected_list.is_valid():
for selection in unselected_list.cleaned_data['selection']:
label = dict(left_list())[selection]
if grouped:
flat_list = []
for group in left_list():
flat_list.extend(group[1])
else:
flat_list = left_list()
label = dict(flat_list)[selection]
if decode_content_type:
selection_obj = get_obj_from_content_type_string(selection)
else:
@@ -86,8 +88,11 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
messages.success(request, _(u'%(selection)s added successfully added to %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
except:
messages.error(request, _(u'Unable to add %(selection)s to %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
if settings.DEBUG:
raise
else:
messages.error(request, _(u'Unable to add %(selection)s to %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
elif u'%s-submit' % right_list_name in request.POST.keys():
selected_list = ChoiceForm(request.POST,
@@ -95,7 +100,14 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
choices=right_list())
if selected_list.is_valid():
for selection in selected_list.cleaned_data['selection']:
label = dict(right_list())[selection]
if grouped:
flat_list = []
for group in right_list():
flat_list.extend(group[1])
else:
flat_list = right_list()
label = dict(flat_list)[selection]
if decode_content_type:
selection = get_obj_from_content_type_string(selection)
try:
@@ -103,8 +115,11 @@ def assign_remove(request, left_list, right_list, add_method, remove_method, lef
messages.success(request, _(u'%(selection)s added successfully removed from %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
except:
messages.error(request, _(u'Unable to add %(selection)s to %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
if settings.DEBUG:
raise
else:
messages.error(request, _(u'Unable to add %(selection)s to %(right_list_title)s.') % {
'selection': label, 'right_list_title': right_list_title})
unselected_list = ChoiceForm(prefix=left_list_name,
choices=left_list())
selected_list = ChoiceForm(prefix=right_list_name,
@@ -168,9 +183,12 @@ def current_user_edit(request):
if request.method == 'POST':
form = UserForm(instance=request.user, data=request.POST)
if form.is_valid():
form.save()
messages.success(request, _(u'Current user\'s details updated.'))
return HttpResponseRedirect(next)
if User.objects.filter(email=form.cleaned_data['email']).exclude(pk=request.user.pk).count():
messages.error(request, _(u'E-mail conflict, another user has that same email.'))
else:
form.save()
messages.success(request, _(u'Current user\'s details updated.'))
return HttpResponseRedirect(next)
else:
form = UserForm(instance=request.user)
@@ -185,34 +203,26 @@ def current_user_edit(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'
"""
"""
kwargs = {'template_name': 'login.html'}
if LOGIN_METHOD == 'email':
kwargs['authentication_form'] = EmailAuthenticationForm
return login(request, **kwargs)
if not request.user.is_authenticated():
context = {'web_theme_view_type': 'plain'}
else:
context = {}
def changelog_view(request):
"""
Display the included Changelog.txt file from the about menu
"""
form = ChangelogForm()
return render_to_response(
'generic_detail.html', {
'form': form,
'title': _(u'Changelog'),
},
context_instance=RequestContext(request))
return login(request, extra_context=context, **kwargs)
def license_view(request):
"""
Display the included LICENSE file from the about menu
"""
"""
form = LicenseForm()
return render_to_response(
'generic_detail.html', {
@@ -220,3 +230,26 @@ def license_view(request):
'title': _(u'License'),
},
context_instance=RequestContext(request))
def password_change_view(request):
"""
Password change wrapper for better control
"""
context={'title': _(u'Current user password change')}
return password_change(
request,
extra_context=context,
template_name='password_change_form.html',
post_change_redirect=reverse('password_change_done'),
)
def password_change_done(request):
"""
View called when the new user password has been accepted
"""
messages.success(request, _(u'Your password has been successfully changed.'))
return redirect('current_user_details')

View File

@@ -13,7 +13,7 @@ class PlainWidget(forms.widgets.Widget):
"""
Class to define a form widget that effectively nulls the htmls of a
widget and reduces the output to only it's value
"""
"""
def render(self, name, value, attrs=None):
return mark_safe(u'%s' % value)
@@ -77,8 +77,8 @@ class TextAreaDiv(forms.widgets.Widget):
"""
Class to define a form widget that simulates the behavior of a
Textarea widget but using a div tag instead
"""
"""
def __init__(self, attrs=None):
# The 'rows' and 'cols' attributes are required for HTML correctness.
default_attrs = {'class': 'text_area_div'}
@@ -99,9 +99,9 @@ class TextAreaDiv(forms.widgets.Widget):
# From: http://www.peterbe.com/plog/emailinput-html5-django
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
"""
"""
input_type = 'email'
def render(self, name, value, attrs=None):
@@ -120,7 +120,8 @@ class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
exceds the height of the div
"""
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
final_attrs = self.build_attrs(attrs, name=name)
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))
output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label))
output.append(u'</ul>')
return mark_safe(u'<div class="text_area_div">%s</div>' % u'\n'.join(output))

View File

@@ -15,7 +15,8 @@ __all__ = ('security_hash', 'BoundFormWizard')
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
order, pickles the result with the SECRET_KEY setting, then takes an md5
@@ -51,19 +52,24 @@ def security_hash_new(form, exclude=None, *args):
class BoundFormWizard(FormWizard):
"""Render prev_fields as a list of bound form fields in the template
context rather than raw html."""
"""
Render prev_fields as a list of bound form fields in the template
context rather than raw html.
"""
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.
Subclasses may want to take into account request-specific information,
such as the IP address.
"""
return security_hash_new(form)
def render(self, form, request, step, context=None):
"Renders the given Form object, returning an HttpResponse."
'Renders the given Form object, returning an HttpResponse.'
old_data = request.POST
prev_fields = []
if old_data:

View File

@@ -1,13 +1,18 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ImproperlyConfigured
from navigation.api import register_sidebar_template
from project_tools.api import register_tool
from converter.utils import load_backend
from converter.conf.settings import GRAPHICS_BACKEND
from .utils import load_backend
from .conf.settings import GRAPHICS_BACKEND
formats_list = {'text': _('file formats'), 'view': 'formats_list', 'famfam': 'pictures', 'icon': 'pictures.png'}
def is_superuser(context):
return context['request'].user.is_staff or context['request'].user.is_superuser
formats_list = {'text': _('file formats'), 'view': 'formats_list', 'famfam': 'pictures', 'icon': 'pictures.png', 'condition': is_superuser, 'children_view_regex': [r'formats_list']}
register_sidebar_template(['formats_list'], 'converter_file_formats_help.html')

View File

@@ -1,25 +1,26 @@
from __future__ import absolute_import
import os
import subprocess
import hashlib
from django.utils.encoding import smart_str
from common.conf.settings import TEMPORARY_DIRECTORY
from converter.literals import DEFAULT_PAGE_NUMBER, \
DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, DEFAULT_FILE_FORMAT
from converter import backend
from converter.literals import TRANSFORMATION_CHOICES
from converter.literals import TRANSFORMATION_RESIZE, \
TRANSFORMATION_ROTATE, TRANSFORMATION_ZOOM
from converter.literals import DIMENSION_SEPARATOR
from converter.literals import FILE_FORMATS
from converter.utils import cleanup
from converter.runtime import office_converter
from converter.exceptions import OfficeConversionError
from .literals import (DEFAULT_PAGE_NUMBER,
DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION, DEFAULT_FILE_FORMAT)
from . import backend
from .literals import (TRANSFORMATION_CHOICES, TRANSFORMATION_RESIZE,
TRANSFORMATION_ROTATE, TRANSFORMATION_ZOOM, DIMENSION_SEPARATOR,
FILE_FORMATS)
from .utils import cleanup
from .runtime import office_converter
from .exceptions import OfficeConversionError, UnknownFileFormat
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
def cache_cleanup(input_filepath, *args, **kwargs):
try:
os.remove(create_image_cache_filename(input_filepath, *args, **kwargs))
@@ -29,7 +30,7 @@ def cache_cleanup(input_filepath, *args, **kwargs):
def create_image_cache_filename(input_filepath, *args, **kwargs):
if input_filepath:
hash_value = HASH_FUNCTION(u''.join([input_filepath, unicode(args), unicode(kwargs)]))
hash_value = HASH_FUNCTION(u''.join([HASH_FUNCTION(smart_str(input_filepath)), unicode(args), unicode(kwargs)]))
return os.path.join(TEMPORARY_DIRECTORY, hash_value)
else:
return None
@@ -42,13 +43,13 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
rotation = kwargs.get('rotation', DEFAULT_ROTATION)
page = kwargs.get('page', DEFAULT_PAGE_NUMBER)
transformations = kwargs.get('transformations', [])
if transformations is None:
transformations = []
if output_filepath is None:
output_filepath = create_image_cache_filename(input_filepath, *args, **kwargs)
if os.path.exists(output_filepath):
return output_filepath
@@ -79,7 +80,7 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
'transformation': TRANSFORMATION_ZOOM,
'arguments': {'percent': zoom}
}
)
)
if rotation != 0 and rotation != 360:
transformations.append(
@@ -87,7 +88,7 @@ def convert(input_filepath, output_filepath=None, cleanup_files=False, mimetype=
'transformation': TRANSFORMATION_ROTATE,
'arguments': {'degrees': rotation}
}
)
)
try:
backend.convert_file(input_filepath=input_filepath, output_filepath=output_filepath, transformations=transformations, page=page, file_format=file_format, mimetype=mimetype)
@@ -106,8 +107,8 @@ def get_page_count(input_filepath):
input_filepath = office_converter.output_filepath
except OfficeConversionError:
raise UnknownFileFormat('office converter exception')
raise UnknownFileFormat('office converter exception')
return backend.get_page_count(input_filepath)
'''
@@ -127,8 +128,7 @@ def get_available_transformations_choices():
result.append([transformation, transformation_template])
return result
def get_format_list():
return [(format, FILE_FORMATS.get(format, u'')) for format in backend.get_format_list()]

View File

@@ -30,7 +30,11 @@ class ConverterClass(ConverterBase):
# If file is a PDF open it with slate to determine the page
# count
with open(input_filepath) as fd:
pages = slate.PDF(fd)
try:
pages = slate.PDF(fd)
except:
return 1
# TODO: Maybe return UnknownFileFormat to display proper unknwon file format message in document description
return len(pages)
try:

View File

@@ -53,7 +53,7 @@ FILE_FORMATS = {
'8BIN': _(u'Photoshop resource format'),
'8BIMTEXT': _(u'Photoshop resource text format'),
'8BIMWTEXT': _(u'Photoshop resource wide text format'),
'A': _(u'Raw alpha samples'),
'AI': _(u'Adobe Illustrator CS2'),
'APP1': _(u'Raw application information'),
@@ -62,7 +62,7 @@ FILE_FORMATS = {
'ARW': _(u'Sony Alpha DSLR Raw Image Format'),
'AVI': _(u'Microsoft Audio/Visual Interleaved'),
'AVS': _(u'AVS X image'),
'B': _(u'Raw blue samples'),
'BGR': _(u'Raw blue, green, and red samples'),
'BGRA': _(u'Raw blue, green, red and alpha samples'),
@@ -95,7 +95,7 @@ FILE_FORMATS = {
'DJVU': _(u'Déjà vu'),
'DNG': _(u'Adobe Digital Negative'),
'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'),
'EPI': _(u'Adobe Encapsulated PostScript Interchange format'),
@@ -110,7 +110,7 @@ FILE_FORMATS = {
'ERF': _(u'Epson RAW Format'),
'EXIF': _(u'Exif digital camera binary data'),
'EXR': _(u'High Dynamic-range (HDR)'),
'FAX': _(u'Group 3 FAX (Not TIFF Group3 FAX)'),
'FLI': _(u'Autodesk FLI animations file'),
'FLC': _(u'Autodesk FLC animations file'),

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,7 +17,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: __init__.py:10
#: __init__.py:15
msgid "file formats"
msgstr ""
@@ -879,15 +879,15 @@ msgstr ""
msgid "CCIR 601 4:1:1 or 4:2:2 (8-bit only)"
msgstr ""
#: views.py:15
#: views.py:17
msgid "suported file formats"
msgstr ""
#: views.py:20
#: views.py:22
msgid "name"
msgstr ""
#: views.py:24
#: views.py:26
msgid "description"
msgstr ""

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -9,9 +9,9 @@ msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"PO-Revision-Date: 2011-11-04 00:24+0000\n"
"Last-Translator: emersonsoares <dev.emerson@gmail.com>\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2011-11-22 15:26+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/"
"team/pt/)\n"
"Language: pt\n"
@@ -20,7 +20,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:10
#: __init__.py:15
msgid "file formats"
msgstr "formatos de arquivo"
@@ -888,15 +888,15 @@ msgstr "Amostras Raw amarelas"
msgid "CCIR 601 4:1:1 or 4:2:2 (8-bit only)"
msgstr "CCIR 601 4:1:1 or 4:2:2 (8-bit only)"
#: views.py:15
#: views.py:17
msgid "suported file formats"
msgstr "formatos de arquivo suportados"
#: views.py:20
#: views.py:22
msgid "name"
msgstr "nome"
#: views.py:24
#: views.py:26
msgid "description"
msgstr "descrição"
@@ -921,9 +921,8 @@ msgstr ""
"imagemagick, converter.backends.graphicsmagick and converter.backends.python."
#: conf/settings.py:16
#, fuzzy
msgid "Path to the unoconv program."
msgstr "Caminho do arquivo para o programa imagemagick converter."
msgstr ""
#: conf/settings.py:17
msgid ""

View File

@@ -1,24 +1,26 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
#
# Translators:
# Sergey Glita <gsv70@mail.ru>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-11-22 11:26-0400\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2011-11-22 19:01+0000\n"
"Last-Translator: gsv70 <gsv70@mail.ru>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/ru/)\n"
"Last-Translator: Sergey Glita <gsv70@mail.ru>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/"
"ru/)\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ru\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:10
#: __init__.py:15
msgid "file formats"
msgstr "форматы файлов"
@@ -630,8 +632,7 @@ msgstr "Joint Photographic Experts Group JFIF format (62)"
#: literals.py:226
msgid "Portable Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)"
msgstr ""
"Portable Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)"
msgstr "Portable Network Graphics (libpng 1.2.42,1.2.44, zlib 1.2.3.3,1.2.3.4)"
#: literals.py:227
msgid ""
@@ -887,15 +888,15 @@ msgstr "Raw yellow samples"
msgid "CCIR 601 4:1:1 or 4:2:2 (8-bit only)"
msgstr "CCIR 601 4:1:1 or 4:2:2 (8-bit only)"
#: views.py:15
#: views.py:17
msgid "suported file formats"
msgstr "поддерживаемые форматы файлов"
#: views.py:20
#: views.py:22
msgid "name"
msgstr "имя"
#: views.py:24
#: views.py:26
msgid "description"
msgstr "описание"
@@ -913,13 +914,11 @@ msgstr "Путь к файлу программs GraphicsMagick."
#: conf/settings.py:15
msgid ""
"Graphics conversion backend to use. Options are: "
"converter.backends.imagemagick, converter.backends.graphicsmagick and "
"converter.backends.python."
"Graphics conversion backend to use. Options are: converter.backends."
"imagemagick, converter.backends.graphicsmagick and converter.backends.python."
msgstr ""
"Конвертер графических файлов. Возможные варианты: "
"converter.backends.imagemagick, converter.backends.graphicsmagick и "
"converter.backends.python."
"Конвертер графических файлов. Возможные варианты: converter.backends."
"imagemagick, converter.backends.graphicsmagick и converter.backends.python."
#: conf/settings.py:16
msgid "Path to the unoconv program."
@@ -927,8 +926,8 @@ msgstr "Путь к программе unoconv."
#: conf/settings.py:17
msgid ""
"Use alternate method of connection to LibreOffice using a pipe, it is slower"
" but less prone to segmentation faults."
"Use alternate method of connection to LibreOffice using a pipe, it is slower "
"but less prone to segmentation faults."
msgstr ""
"Использовать альтернативный способ подключения к LibreOffice использованием "
"конвейера pipe, это медленнее, но менее опасно ошибкой сегментации."
@@ -944,5 +943,3 @@ msgid ""
"backend. In this case: '%(backend)s'"
msgstr ""
"Эти форматы поддерживают выбранный конвертер. Сейчас это: '%(backend)s'"

View File

@@ -1,3 +1,5 @@
from __future__ import absolute_import
import os
import subprocess
import logging
@@ -6,19 +8,19 @@ from mimetype.api import get_mimetype
from common.conf.settings import TEMPORARY_DIRECTORY
from common.utils import id_generator
from converter.conf.settings import UNOCONV_PATH, UNOCONV_USE_PIPE
from converter.exceptions import (OfficeConversionError,
from .conf.settings import UNOCONV_PATH, UNOCONV_USE_PIPE
from .exceptions import (OfficeConversionError,
OfficeBackendError, UnknownFileFormat)
CACHED_FILE_SUFFIX = u'_office_converter'
CONVERTER_OFFICE_FILE_MIMETYPES = [
u'application/msword',
u'application/mswrite',
u'application/mspowerpoint',
u'application/msexcel',
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.text',
u'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
@@ -41,7 +43,7 @@ class OfficeConverter(object):
self.exists = False
self.mimetype = None
self.encoding = None
def mimetypes(self):
return CONVERTER_OFFICE_FILE_MIMETYPES
@@ -49,7 +51,7 @@ class OfficeConverter(object):
self.exists = False
self.mimetype = None
self.encoding = None
self.input_filepath = input_filepath
# Make sure file is of a known office format
@@ -69,13 +71,13 @@ class OfficeConverter(object):
except OfficeBackendError, msg:
# convert exception so that at least the mime type icon is displayed
raise UnknownFileFormat(msg)
def __unicode__(self):
return getattr(self, 'output_filepath', None)
def __str__(self):
return str(self.__unicode__())
class OfficeConverterBackendUnoconv(object):
def __init__(self):
@@ -89,7 +91,7 @@ class OfficeConverterBackendUnoconv(object):
'''
self.input_filepath = input_filepath
self.output_filepath = output_filepath
command = []
command.append(self.unoconv_path)

View File

@@ -1,5 +1,7 @@
from converter.office_converter import OfficeConverter
from converter.exceptions import OfficeBackendError
from __future__ import absolute_import
from .office_converter import OfficeConverter
from .exceptions import OfficeBackendError
try:

View File

@@ -20,4 +20,3 @@ Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

View File

@@ -1,32 +1,36 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.core.exceptions import PermissionDenied
from common.utils import encapsulate
from converter.api import get_format_list
from converter.conf.settings import GRAPHICS_BACKEND
from .api import get_format_list
from .conf.settings import GRAPHICS_BACKEND
def formats_list(request):
#check_permissions(request.user, [PERMISSION_DOCUMENT_VIEW])
if request.user.is_superuser or request.user.is_staff:
context = {
'title': _(u'suported file formats'),
'hide_object': True,
'object_list': sorted(get_format_list()),
'extra_columns': [
{
'name': _(u'name'),
'attribute': encapsulate(lambda x: x[0])
},
{
'name': _(u'description'),
'attribute': encapsulate(lambda x: x[1])
}
],
'backend': GRAPHICS_BACKEND,
}
context = {
'title': _(u'suported file formats'),
'hide_object': True,
'object_list': sorted(get_format_list()),
'extra_columns': [
{
'name': _(u'name'),
'attribute': encapsulate(lambda x: x[0])
},
{
'name': _(u'description'),
'attribute': encapsulate(lambda x: x[1])
}
],
'backend': GRAPHICS_BACKEND,
}
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
return render_to_response('generic_list.html', context,
context_instance=RequestContext(request))
else:
raise PermissionDenied

View File

@@ -1,39 +1,14 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from documents.models import Document
from navigation.api import register_links, register_top_menu, \
register_model_list_columns, register_multi_item_links, \
register_sidebar_template
from main.api import register_diagnostic, register_maintenance_links
from permissions.api import register_permission, set_namespace_title
from navigation.api import register_links
from project_setup.api import register_setup
from hkp import Key as KeyServerKey
from django_gpg.api import Key
PERMISSION_DOCUMENT_VERIFY = {'namespace': 'django_gpg', 'name': 'document_verify', 'label': _(u'Verify document signatures')}
PERMISSION_KEY_VIEW = {'namespace': 'django_gpg', 'name': 'key_view', 'label': _(u'View keys')}
PERMISSION_KEY_DELETE = {'namespace': 'django_gpg', 'name': 'key_delete', 'label': _(u'Delete keys')}
PERMISSION_KEYSERVER_QUERY = {'namespace': 'django_gpg', 'name': 'keyserver_query', 'label': _(u'Query keyservers')}
PERMISSION_KEY_RECEIVE = {'namespace': 'django_gpg', 'name': 'key_receive', 'label': _(u'Import key from keyservers')}
PERMISSION_SIGNATURE_UPLOAD = {'namespace': 'django_gpg', 'name': 'signature_upload', 'label': _(u'Upload detached signatures')}
PERMISSION_SIGNATURE_DOWNLOAD = {'namespace': 'django_gpg', 'name': 'key_receive', 'label': _(u'Download detached signatures')}
# Permission setup
set_namespace_title('django_gpg', _(u'Signatures'))
register_permission(PERMISSION_DOCUMENT_VERIFY)
register_permission(PERMISSION_KEY_VIEW)
register_permission(PERMISSION_KEY_DELETE)
register_permission(PERMISSION_KEYSERVER_QUERY)
register_permission(PERMISSION_KEY_RECEIVE)
register_permission(PERMISSION_SIGNATURE_UPLOAD)
register_permission(PERMISSION_SIGNATURE_DOWNLOAD)
def has_embedded_signature(context):
return context['object'].signature_state
def doesnt_have_detached_signature(context):
return context['object'].has_detached_signature() == False
from .api import Key
from .permissions import (PERMISSION_KEY_VIEW, PERMISSION_KEY_DELETE,
PERMISSION_KEYSERVER_QUERY, PERMISSION_KEY_RECEIVE)
# Setup views
private_keys = {'text': _(u'private keys'), 'view': 'key_private_list', 'args': 'object.pk', 'famfam': 'key', 'icon': 'key.png', 'permissions': [PERMISSION_KEY_VIEW]}
@@ -41,16 +16,7 @@ public_keys = {'text': _(u'public keys'), 'view': 'key_public_list', 'args': 'ob
key_delete = {'text': _(u'delete'), 'view': 'key_delete', 'args': ['object.fingerprint', 'object.type'], 'famfam': 'key_delete', 'permissions': [PERMISSION_KEY_DELETE]}
key_query = {'text': _(u'query keyservers'), 'view': 'key_query', 'famfam': 'zoom', 'permissions': [PERMISSION_KEYSERVER_QUERY]}
key_receive = {'text': _(u'import'), 'view': 'key_receive', 'args': 'object.keyid', 'famfam': 'key_add', 'keep_query': True, 'permissions': [PERMISSION_KEY_RECEIVE]}
document_signature_upload = {'text': _(u'upload signature'), 'view': 'document_signature_upload', 'args': 'object.pk', 'famfam': 'pencil_add', 'permissions': [PERMISSION_SIGNATURE_UPLOAD], 'conditional_disable': has_embedded_signature}
document_signature_download = {'text': _(u'download signature'), 'view': 'document_signature_download', 'args': 'object.pk', 'famfam': 'disk', 'permissions': [PERMISSION_SIGNATURE_DOWNLOAD], 'conditional_disable': doesnt_have_detached_signature}
key_setup = {'text': _(u'key management'), 'view': 'key_public_list', 'args': 'object.pk', 'famfam': 'key', 'icon': 'key.png', 'permissions': [PERMISSION_KEY_VIEW]}
# Document views
document_verify = {'text': _(u'signatures'), 'view': 'document_verify', 'args': 'object.pk', 'famfam': 'text_signature', 'permissions': [PERMISSION_DOCUMENT_VERIFY]}
register_links(Document, [document_verify], menu_name='form_header')
register_links(['document_verify', 'document_signature_upload', 'document_signature_download'], [document_signature_upload, document_signature_download], menu_name='sidebar')
key_setup = {'text': _(u'key management'), 'view': 'key_public_list', 'args': 'object.pk', 'famfam': 'key', 'icon': 'key.png', 'permissions': [PERMISSION_KEY_VIEW], 'children_view_regex': [r'^key_']}
#register_links(['key_delete', 'key_private_list', 'key_public_list', 'key_query'], [private_keys, public_keys, key_query], menu_name='sidebar')
register_links(['key_delete', 'key_public_list', 'key_query'], [public_keys, key_query], menu_name='sidebar')
@@ -59,6 +25,3 @@ register_links(Key, [key_delete])
register_links(KeyServerKey, [key_receive])
register_setup(key_setup)

View File

@@ -1,18 +1,20 @@
import types
from StringIO import StringIO
from pickle import dumps
from __future__ import absolute_import
import logging
import tempfile
import os
from django.core.files.base import File
try:
from cStringIO import StringIO
except ImportError:
from StringIO import StringIO
from django.utils.translation import ugettext_lazy as _
from django.utils.http import urlquote_plus
from hkp import KeyServer
import gnupg
from django_gpg.exceptions import (GPGVerificationError, GPGSigningError,
from .exceptions import (GPGVerificationError, GPGSigningError,
GPGDecryptionError, KeyDeleteError, KeyGenerationError,
KeyFetchingError, KeyDoesNotExist, KeyImportError)
@@ -71,7 +73,7 @@ SIGNATURE_STATES = {
'text': _(u'Document is signed with a valid signature.'),
'icon': 'document_signature.png'
},
}
}
class Key(object):
@@ -108,7 +110,7 @@ class Key(object):
keys = gpg.gpg.list_keys(secret=secret)
key = next((key for key in keys if key['keyid'] == key_id), None)
if not key:
if search_keyservers and secret==False:
if search_keyservers and secret == False:
try:
gpg.receive_key(key_id)
return Key(gpg, key_id)
@@ -151,6 +153,17 @@ class Key(object):
class GPG(object):
@staticmethod
def get_descriptor(file_input):
try:
# Is it a file like object?
file_input.seek(0)
except AttributeError:
# If not, try open it.
return open(file_input, 'rb')
else:
return file_input
def __init__(self, binary_path=None, home=None, keyring=None, keyservers=None):
kwargs = {}
if binary_path:
@@ -166,60 +179,45 @@ class GPG(object):
self.gpg = gnupg.GPG(**kwargs)
def verify_w_retry(self, file_input, detached_signature=None):
if isinstance(file_input, types.StringTypes):
input_descriptor = open(file_input, 'rb')
elif isinstance(file_input, types.FileType) or isinstance(file_input, File):
input_descriptor = file_input
elif issubclass(file_input.__class__, StringIO):
input_descriptor = file_input
else:
raise ValueError('Invalid file_input argument type')
try:
verify = self.verify_file(input_descriptor, detached_signature)
if verify.status == 'no public key':
# Try to fetch the public key from the keyservers
try:
self.receive_key(verify.key_id)
return self.verify_w_retry(file_input, detached_signature)
except KeyFetchingError:
return verify
else:
return verify
except IOError:
return False
def verify_file(self, file_input, detached_signature=None):
def verify_file(self, file_input, detached_signature=None, fetch_key=False):
"""
Verify the signature of a file.
"""
if isinstance(file_input, types.StringTypes):
descriptor = open(file_input, 'rb')
elif isinstance(file_input, types.FileType) or isinstance(file_input, File) or isinstance(file_input, StringIO):
descriptor = file_input
else:
raise ValueError('Invalid file_input argument type')
input_descriptor = GPG.get_descriptor(file_input)
if detached_signature:
# Save the original data and invert the argument order
# Signature first, file second
file_descriptor, filename = tempfile.mkstemp(prefix='django_gpg')
file_data = file_input.read()
file_input.close()
os.write(file_descriptor, file_data)
os.write(file_descriptor, input_descriptor.read())
os.close(file_descriptor)
verify = self.gpg.verify_file(detached_signature, data_filename=filename)
detached_signature = GPG.get_descriptor(detached_signature)
signature_file = StringIO()
signature_file.write(detached_signature.read())
signature_file.seek(0)
verify = self.gpg.verify_file(signature_file, data_filename=filename)
signature_file.close()
else:
verify = self.gpg.verify_file(descriptor)
descriptor.close()
verify = self.gpg.verify_file(input_descriptor)
logger.debug('verify.status: %s' % getattr(verify, 'status', None))
if verify:
logger.debug('verify ok')
return verify
#elif getattr(verify, 'status', None) == 'no public key':
# # Exception to the rule, to be able to query the keyservers
# return verify
elif getattr(verify, 'status', None) == 'no public key':
# Exception to the rule, to be able to query the keyservers
if fetch_key:
try:
self.receive_key(verify.key_id)
return self.verify_file(input_descriptor, detached_signature, fetch_key=False)
except KeyFetchingError:
return verify
else:
return verify
else:
logger.debug('No verify')
raise GPGVerificationError()
def verify(self, data):
@@ -238,6 +236,7 @@ class GPG(object):
overrided if it already exists), if no destination file name is
provided the signature is returned.
"""
kwargs = {}
kwargs['clearsign'] = clearsign
@@ -250,14 +249,7 @@ class GPG(object):
if passphrase:
kwargs['passphrase'] = passphrase
if isinstance(file_input, types.StringTypes):
input_descriptor = open(file_input, 'rb')
elif isinstance(file_input, types.FileType) or isinstance(file_input, File):
input_descriptor = file_input
elif issubclass(file_input.__class__, StringIO):
input_descriptor = file_input
else:
raise ValueError('Invalid file_input argument type')
input_descriptor = GPG.get_descriptor(file_input)
if destination:
output_descriptor = open(destination, 'wb')
@@ -277,21 +269,26 @@ class GPG(object):
if not destination:
return signed_data
def decrypt_file(self, file_input):
if isinstance(file_input, types.StringTypes):
input_descriptor = open(file_input, 'rb')
elif isinstance(file_input, types.FileType) or isinstance(file_input, File) or isinstance(file_input, StringIO):
input_descriptor = file_input
def has_embedded_signature(self, *args, **kwargs):
try:
self.decrypt_file(*args, **kwargs)
except GPGDecryptionError:
return False
else:
raise ValueError('Invalid file_input argument type')
return True
def decrypt_file(self, file_input, close_descriptor=True):
input_descriptor = GPG.get_descriptor(file_input)
result = self.gpg.decrypt_file(input_descriptor)
input_descriptor.close()
if close_descriptor:
input_descriptor.close()
if not result.status:
raise GPGDecryptionError('Unable to decrypt file')
return result
def create_key(self, *args, **kwargs):
if kwargs.get('passphrase') == u'':
kwargs.pop('passphrase')
@@ -318,7 +315,7 @@ class GPG(object):
return Key.get(self, import_result.fingerprints[0], secret=False)
raise KeyFetchingError
def query(self, term):
results = {}
for keyserver in self.keyservers:
@@ -330,14 +327,14 @@ class GPG(object):
results[key.keyid] = key
except:
pass
return results.values()
def import_key(self, key_data):
import_result = self.gpg.import_keys(key_data)
logger.debug('import_result: %s' % import_result)
if import_result:
return Key.get(self, import_result.fingerprints[0], secret=False)
raise KeyImportError
raise KeyImportError(import_result.results)

View File

@@ -1,8 +1,10 @@
'''
"""
Configuration options for the django_gpg app
'''
"""
import os
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from smart_settings.api import register_settings
@@ -11,5 +13,6 @@ register_settings(
module=u'django_gpg.conf.settings',
settings=[
{'name': u'KEYSERVERS', 'global_name': u'SIGNATURES_KEYSERVERS', 'default': ['pool.sks-keyservers.net'], 'description': _(u'List of keyservers to be queried for unknown keys.')},
{'name': u'GPG_HOME', 'global_name': u'SIGNATURES_GPG_HOME', 'default': os.path.join(settings.PROJECT_ROOT, u'gpg_home'), 'description': _(u'Home directory used to store keys as well as configuration files.')},
]
)

View File

@@ -1,9 +1,5 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
from django.conf import settings
class KeySearchForm(forms.Form):
@@ -11,9 +7,3 @@ class KeySearchForm(forms.Form):
label=_(u'Term'),
help_text=_(u'Name, e-mail, key ID or key fingerprint to look for.')
)
class DetachedSignatureForm(forms.Form):
file = forms.FileField(
label=_(u'Signature file'),
)

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-06 02:06-0400\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,142 +17,114 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: __init__.py:14
msgid "Verify document signatures"
msgstr ""
#: __init__.py:15
msgid "View keys"
msgstr ""
#: __init__.py:16
msgid "Delete keys"
msgstr ""
#: __init__.py:17
msgid "Query keyservers"
msgstr ""
#: __init__.py:18
msgid "Import key from keyservers"
msgstr ""
#: __init__.py:19
msgid "Upload detached signatures"
msgstr ""
#: __init__.py:20
msgid "Download detached signatures"
msgstr ""
#: __init__.py:23
msgid "Signatures"
msgstr ""
#: __init__.py:39 views.py:67
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr ""
#: __init__.py:40 views.py:70
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr ""
#: __init__.py:41
#: __init__.py:16
msgid "delete"
msgstr ""
#: __init__.py:42
#: __init__.py:17
msgid "query keyservers"
msgstr ""
#: __init__.py:43
#: __init__.py:18
msgid "import"
msgstr ""
#: __init__.py:44
msgid "upload signature"
msgstr ""
#: __init__.py:45
msgid "download signature"
msgstr ""
#: __init__.py:46
#: __init__.py:19
msgid "key management"
msgstr ""
#: __init__.py:49
msgid "signatures"
msgstr ""
#: api.py:22
#: api.py:19
msgid "Public"
msgstr ""
#: api.py:23
#: api.py:20
msgid "Secret"
msgstr ""
#: api.py:31 api.py:36
#: api.py:28 api.py:33
msgid "RSA"
msgstr ""
#: api.py:32
#: api.py:29
msgid "DSA"
msgstr ""
#: api.py:37
#: api.py:34
msgid "Elgamal"
msgstr ""
#: api.py:51
#: api.py:48
msgid "Bad signature."
msgstr ""
#: api.py:55
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr ""
#: api.py:59
#: api.py:56
msgid "Signature error."
msgstr ""
#: api.py:63
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr ""
#: api.py:67
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr ""
#: api.py:71
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr ""
#: api.py:144
#: api.py:141
msgid "unknown"
msgstr ""
#: forms.py:11
#: forms.py:8
msgid "Term"
msgstr ""
#: forms.py:12
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr ""
#: forms.py:18
msgid "Signature file"
#: permissions.py:7
msgid "Key management"
msgstr ""
#: views.py:45
#: permissions.py:9
msgid "View keys"
msgstr ""
#: permissions.py:10
msgid "Delete keys"
msgstr ""
#: permissions.py:11
msgid "Query keyservers"
msgstr ""
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr ""
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr ""
#: views.py:48
#: views.py:43
#, python-format
msgid "Unable to import key id: %s"
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr ""
#: views.py:52
@@ -233,58 +205,10 @@ msgstr ""
msgid "Identifies"
msgstr ""
#: views.py:205
#, python-format
msgid "Signature status: %(widget)s %(text)s"
msgstr ""
#: views.py:212
msgid "embedded"
msgstr ""
#: views.py:214
msgid "detached"
msgstr ""
#: views.py:219
#, python-format
msgid "Signature ID: %s"
msgstr ""
#: views.py:220
#, python-format
msgid "Signature type: %s"
msgstr ""
#: views.py:221
#, python-format
msgid "Key ID: %s"
msgstr ""
#: views.py:222
#, python-format
msgid "Timestamp: %s"
msgstr ""
#: views.py:223
#, python-format
msgid "Signee: %s"
msgstr ""
#: views.py:228
#, python-format
msgid "signature properties for: %s"
msgstr ""
#: views.py:250
msgid "Detached signature uploaded successfully."
msgstr ""
#: views.py:259
#, python-format
msgid "Upload detached signature for: %s"
msgstr ""
#: conf/settings.py:13
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr ""
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr ""

View File

@@ -1,164 +1,137 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2011.
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2011, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2011-12-06 02:06-0400\n"
"PO-Revision-Date: 2011-12-06 06:14+0000\n"
"Last-Translator: rosarior <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/mayan-edms/team/es/)\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:37+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Spanish (Castilian) (http://www.transifex.net/projects/p/"
"mayan-edms/team/es/)\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: es\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14
msgid "Verify document signatures"
msgstr "Verificar las firmas de documentos"
#: __init__.py:15
msgid "View keys"
msgstr "Ver llaves"
#: __init__.py:16
msgid "Delete keys"
msgstr "Borrar llaves"
#: __init__.py:17
msgid "Query keyservers"
msgstr "Hacer búsquedas en servidores de llaves"
#: __init__.py:18
msgid "Import key from keyservers"
msgstr "Importar llaves de los servidores de llaves"
#: __init__.py:19
msgid "Upload detached signatures"
msgstr "Subir una firma a parte"
#: __init__.py:20
msgid "Download detached signatures"
msgstr "Descargar la fima"
#: __init__.py:23
msgid "Signatures"
msgstr "Firmas"
#: __init__.py:39 views.py:67
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr "llaves privadas"
#: __init__.py:40 views.py:70
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr "llaves públicas"
#: __init__.py:41
#: __init__.py:16
msgid "delete"
msgstr "borrar"
#: __init__.py:42
#: __init__.py:17
msgid "query keyservers"
msgstr "consultar servidor de llaves"
#: __init__.py:43
#: __init__.py:18
msgid "import"
msgstr "importar"
#: __init__.py:44
msgid "upload signature"
msgstr "subir firma"
#: __init__.py:45
msgid "download signature"
msgstr "descargar firma"
#: __init__.py:46
#: __init__.py:19
msgid "key management"
msgstr "manejo de llaves"
#: __init__.py:49
msgid "signatures"
msgstr "firmas"
#: api.py:22
#: api.py:19
msgid "Public"
msgstr "Pública"
#: api.py:23
#: api.py:20
msgid "Secret"
msgstr "Secreta"
#: api.py:31 api.py:36
#: api.py:28 api.py:33
msgid "RSA"
msgstr "RSA"
#: api.py:32
#: api.py:29
msgid "DSA"
msgstr "DSA"
#: api.py:37
#: api.py:34
msgid "Elgamal"
msgstr "Elgamal"
#: api.py:51
#: api.py:48
msgid "Bad signature."
msgstr "Firma invalida."
#: api.py:55
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr "Documento no firmado o firma invalida."
#: api.py:59
#: api.py:56
msgid "Signature error."
msgstr "Error de firma."
#: api.py:63
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr ""
"El document ha sido firmado pero no hay llave pública disponible para "
"verificación."
#: api.py:67
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr "El document ha sido firmado y la firma esta es buen estado."
#: api.py:71
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr "El document ha sido firmado y la firma ha sido validada."
#: api.py:144
#: api.py:141
msgid "unknown"
msgstr "desconocida"
#: forms.py:11
#: forms.py:8
msgid "Term"
msgstr "Término"
#: forms.py:12
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr ""
"Nombre, dirección de correo electrónico, identificador de llave or huella "
"digital de llave a buscar."
#: forms.py:18
msgid "Signature file"
msgstr "Archivo de firma"
#: permissions.py:7
msgid "Key management"
msgstr "Gestión de llaves"
#: views.py:45
#: permissions.py:9
msgid "View keys"
msgstr "Ver llaves"
#: permissions.py:10
msgid "Delete keys"
msgstr "Borrar llaves"
#: permissions.py:11
msgid "Query keyservers"
msgstr "Hacer búsquedas en servidores de llaves"
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr "Importar llaves del servidores de llaves"
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr "Llave: %s, importada exitosamente."
#: views.py:48
#: views.py:43
#, python-format
msgid "Unable to import key id: %s"
msgstr "No se pudo importa la llave: %s"
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr "No se pudo importar la llave: %(key_id)s ; %(error)s "
#: views.py:52
msgid "Import key"
@@ -194,8 +167,8 @@ msgid ""
"well."
msgstr ""
"¿Esta seguro que desea borrar la llave: %s? Si trata de borrar una llave "
"pública que es parte de un par público/privado la llave privada será borrada"
" también."
"pública que es parte de un par público/privado la llave privada será borrada "
"también."
#: views.py:129
msgid "Query key server"
@@ -241,62 +214,14 @@ msgstr "revocada"
msgid "Identifies"
msgstr "Identidades"
#: views.py:205
#, python-format
msgid "Signature status: %(widget)s %(text)s"
msgstr "Estado de la firma: %(widget)s %(text)s"
#: views.py:212
msgid "embedded"
msgstr "integrada"
#: views.py:214
msgid "detached"
msgstr "a parte"
#: views.py:219
#, python-format
msgid "Signature ID: %s"
msgstr "ID de la firma: %s"
#: views.py:220
#, python-format
msgid "Signature type: %s"
msgstr "Tipo de firma: %s"
#: views.py:221
#, python-format
msgid "Key ID: %s"
msgstr "ID de la llave: %s"
#: views.py:222
#, python-format
msgid "Timestamp: %s"
msgstr "Fecha y hora: %s"
#: views.py:223
#, python-format
msgid "Signee: %s"
msgstr "Firmantes: %s"
#: views.py:228
#, python-format
msgid "signature properties for: %s"
msgstr "propiedades de firma para: %s"
#: views.py:250
msgid "Detached signature uploaded successfully."
msgstr "El archivo de firma fue subido exitosamente."
#: views.py:259
#, python-format
msgid "Upload detached signature for: %s"
msgstr "Subir firma a parte para: %s"
#: conf/settings.py:13
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr ""
"Lista de servidores de llaves a ser utilizados para buscar llaves "
"desconocidas."
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr ""
"Directorio de inicio utilizado para almacenar las llaves, así como los "
"archivos de configuración."

Binary file not shown.

View File

@@ -0,0 +1,221 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# <pierpaolo.baldan@gmail.com>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:20+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Italian (http://www.transifex.net/projects/p/mayan-edms/team/"
"it/)\n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr "Chiave privata"
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr "Chiave pubblica"
#: __init__.py:16
msgid "delete"
msgstr "cancella"
#: __init__.py:17
msgid "query keyservers"
msgstr "Interroga il server delle chiavi"
#: __init__.py:18
msgid "import"
msgstr "import"
#: __init__.py:19
msgid "key management"
msgstr "gestione della firma"
#: api.py:19
msgid "Public"
msgstr "Pubblica"
#: api.py:20
msgid "Secret"
msgstr "Segreta"
#: api.py:28 api.py:33
msgid "RSA"
msgstr "RSA"
#: api.py:29
msgid "DSA"
msgstr "DSA"
#: api.py:34
msgid "Elgamal"
msgstr "Elgamal"
#: api.py:48
msgid "Bad signature."
msgstr "Firma cattiva."
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr "Documento non firmato o firma invalida."
#: api.py:56
msgid "Signature error."
msgstr "Errore di firma"
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr ""
"Il documento è stato firmato, ma la chiave pubblica non è disponibile per la "
"verifica"
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr "Documento firmato e firma è buona."
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr "Il documento è firmato con una firma valida."
#: api.py:141
msgid "unknown"
msgstr "sconosciuto"
#: forms.py:8
msgid "Term"
msgstr "Scadenza"
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr "Nome, e-mail,key ID , impronte digitali per cercare"
#: permissions.py:7
msgid "Key management"
msgstr ""
#: permissions.py:9
msgid "View keys"
msgstr "Vista delle chiavi"
#: permissions.py:10
msgid "Delete keys"
msgstr "Cancella chiavi"
#: permissions.py:11
msgid "Query keyservers"
msgstr "Interroga l'autorità per le chiavi"
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr ""
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr "Chiave: %s, importata con successo."
#: views.py:43
#, python-format
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr ""
#: views.py:52
msgid "Import key"
msgstr "Importa chiave"
#: views.py:53
#, python-format
msgid "Are you sure you wish to import key id: %s?"
msgstr "Sei sicuro di voler importare la chiave id: %s?"
#: views.py:78
msgid "Key ID"
msgstr "chiave ID"
#: views.py:82
msgid "Owner"
msgstr "Proprietario"
#: views.py:102
#, python-format
msgid "Key: %s, deleted successfully."
msgstr "chiave: %s, cancellata con successo."
#: views.py:109
msgid "Delete key"
msgstr "Cancella chiave"
#: views.py:111
#, python-format
msgid ""
"Are you sure you wish to delete key: %s? If you try to delete a public key "
"that is part of a public/private pair the private key will be deleted as "
"well."
msgstr ""
"Sei sicuro di voler cancellare la chiave: %s? Se provi a cancellare una "
"chiave pubblica che è parte di una coppia publica/privata anche la chiave "
"privata sarà cancellata"
#: views.py:129
msgid "Query key server"
msgstr "Interroga il server delle chiavi"
#: views.py:142
msgid "results"
msgstr "risultati"
#: views.py:147
msgid "ID"
msgstr "ID"
#: views.py:151
msgid "type"
msgstr "tipo"
#: views.py:155
msgid "creation date"
msgstr "data di crezione"
#: views.py:159
msgid "disabled"
msgstr "disabilitata"
#: views.py:163
msgid "expiration date"
msgstr "data scadenza"
#: views.py:167
msgid "expired"
msgstr "scaduta"
#: views.py:171
msgid "length"
msgstr "lunghezza"
#: views.py:175
msgid "revoked"
msgstr "revocata"
#: views.py:180
msgid "Identifies"
msgstr "Identifica"
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr "Lista di server per chiavi che si possono interrogare."
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr ""

Binary file not shown.

View File

@@ -0,0 +1,215 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# <winterfall24@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: http://github.com/rosarior/mayan/issues\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-21 20:34+0000\n"
"Last-Translator: mic <winterfall24@gmail.com>\n"
"Language-Team: Polish (http://www.transifex.net/projects/p/mayan-edms/language/pl/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: pl\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr "private keys"
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr "public keys"
#: __init__.py:16
msgid "delete"
msgstr "usunąć"
#: __init__.py:17
msgid "query keyservers"
msgstr "query keyservers"
#: __init__.py:18
msgid "import"
msgstr "import"
#: __init__.py:19
msgid "key management"
msgstr "zarządzanie kluczami"
#: api.py:19
msgid "Public"
msgstr "Publiczny"
#: api.py:20
msgid "Secret"
msgstr "Secret"
#: api.py:28 api.py:33
msgid "RSA"
msgstr "RSA"
#: api.py:29
msgid "DSA"
msgstr "DSA"
#: api.py:34
msgid "Elgamal"
msgstr "Elgamal"
#: api.py:48
msgid "Bad signature."
msgstr "Zły podpis."
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr "Dokumentu nie podpisany lub nieprawidłowy podpis."
#: api.py:56
msgid "Signature error."
msgstr "Błąd podpisu."
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr "Dokument został podpisany, ale klucz publiczny nie jest dostępny do weryfikacji."
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr "Dokument został podpisany, a podpis jest dobry."
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr "Dokument podpisany za pomocą ważnego podpisu."
#: api.py:141
msgid "unknown"
msgstr "nieznany"
#: forms.py:8
msgid "Term"
msgstr "Term"
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr "Imię i nazwisko, e-mail, key ID lub key fingerprint kluc szukać."
#: permissions.py:7
msgid "Key management"
msgstr "Zarządzanie kluczami"
#: permissions.py:9
msgid "View keys"
msgstr "View keys"
#: permissions.py:10
msgid "Delete keys"
msgstr "Delete keys"
#: permissions.py:11
msgid "Query keyservers"
msgstr "Query keyservers"
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr "Import keys from keyservers"
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr "Klucz:%s, zaimportowany."
#: views.py:43
#, python-format
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr "Nie można zaimportować ID klucza: %(key_id)s ; %(error)s "
#: views.py:52
msgid "Import key"
msgstr "Importuj klucz"
#: views.py:53
#, python-format
msgid "Are you sure you wish to import key id: %s?"
msgstr "Czy na pewno chcesz importować ID klucza:%s?"
#: views.py:78
msgid "Key ID"
msgstr "Key ID"
#: views.py:82
msgid "Owner"
msgstr "Właściciel"
#: views.py:102
#, python-format
msgid "Key: %s, deleted successfully."
msgstr "Klucz:%s, został usunięty."
#: views.py:109
msgid "Delete key"
msgstr "Usuń klucz"
#: views.py:111
#, python-format
msgid ""
"Are you sure you wish to delete key: %s? If you try to delete a public key "
"that is part of a public/private pair the private key will be deleted as "
"well."
msgstr "Czy na pewno chcesz usunąć klucz:%s? Jeśli próbujesz usunąć klucza publiczny, który jest częścią pary publiczny / prywatny klucz prywatny zostanie usunięty również."
#: views.py:129
msgid "Query key server"
msgstr "Query key server"
#: views.py:142
msgid "results"
msgstr "wyniki"
#: views.py:147
msgid "ID"
msgstr "ID"
#: views.py:151
msgid "type"
msgstr "typ"
#: views.py:155
msgid "creation date"
msgstr "creation date"
#: views.py:159
msgid "disabled"
msgstr "wyłączone"
#: views.py:163
msgid "expiration date"
msgstr "data ważności"
#: views.py:167
msgid "expired"
msgstr "wygasł"
#: views.py:171
msgid "length"
msgstr "długość"
#: views.py:175
msgid "revoked"
msgstr "odwołany"
#: views.py:180
msgid "Identifies"
msgstr "Identyfikuje"
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr "List of keyservers to be queried for unknown keys."
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr "Katalog domowy używany do przechowywania kluczy oraz plików konfiguracyjnych."

View File

@@ -3,13 +3,14 @@
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Roberto Rosario <roberto.rosario.gonzalez@gmail.com>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-06 02:06-0400\n"
"PO-Revision-Date: 2011-12-05 17:43+0000\n"
"Last-Translator: rosarior <roberto.rosario.gonzalez@gmail.com>\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:20+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Portuguese (http://www.transifex.net/projects/p/mayan-edms/"
"team/pt/)\n"
"Language: pt\n"
@@ -18,169 +19,141 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
#: __init__.py:14
msgid "Verify document signatures"
msgstr ""
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr "chaves privadas"
#: __init__.py:15
msgid "View keys"
msgstr ""
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr "chaves públicas"
#: __init__.py:16
msgid "Delete keys"
msgstr ""
msgid "delete"
msgstr "excluir"
#: __init__.py:17
msgid "Query keyservers"
msgstr ""
#: __init__.py:18
msgid "Import key from keyservers"
msgstr ""
#: __init__.py:19
msgid "Upload detached signatures"
msgstr ""
#: __init__.py:20
msgid "Download detached signatures"
msgstr ""
#: __init__.py:23
msgid "Signatures"
msgstr ""
#: __init__.py:39 views.py:67
msgid "private keys"
msgstr ""
#: __init__.py:40 views.py:70
msgid "public keys"
msgstr ""
#: __init__.py:41
msgid "delete"
msgstr ""
#: __init__.py:42
msgid "query keyservers"
msgstr ""
#: __init__.py:43
#: __init__.py:18
msgid "import"
msgstr ""
#: __init__.py:44
msgid "upload signature"
msgstr ""
#: __init__.py:45
msgid "download signature"
msgstr ""
#: __init__.py:46
#: __init__.py:19
msgid "key management"
msgstr ""
#: __init__.py:49
msgid "signatures"
msgstr ""
#: api.py:22
#: api.py:19
msgid "Public"
msgstr ""
msgstr "Público"
#: api.py:23
#: api.py:20
msgid "Secret"
msgstr ""
msgstr "Segredo"
#: api.py:31 api.py:36
#: api.py:28 api.py:33
msgid "RSA"
msgstr ""
msgstr "RSA"
#: api.py:32
#: api.py:29
msgid "DSA"
msgstr ""
msgstr "DSA"
#: api.py:37
#: api.py:34
msgid "Elgamal"
msgstr ""
msgstr "Elgamal"
#: api.py:51
#: api.py:48
msgid "Bad signature."
msgstr ""
msgstr "Assinatura ruim."
#: api.py:55
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr ""
msgstr "Documento não assinado ou inválido assinatura."
#: api.py:59
#: api.py:56
msgid "Signature error."
msgstr ""
msgstr "Erro de assinatura."
#: api.py:63
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr ""
#: api.py:67
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr ""
#: api.py:71
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr ""
#: api.py:144
#: api.py:141
msgid "unknown"
msgstr ""
msgstr "desconhecido"
#: forms.py:11
#: forms.py:8
msgid "Term"
msgstr ""
#: forms.py:12
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr ""
#: forms.py:18
msgid "Signature file"
#: permissions.py:7
msgid "Key management"
msgstr ""
#: views.py:45
#: permissions.py:9
msgid "View keys"
msgstr "Ver as chaves"
#: permissions.py:10
msgid "Delete keys"
msgstr "Excluir chaves"
#: permissions.py:11
msgid "Query keyservers"
msgstr "Consulta servidores de chaves"
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr ""
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr ""
#: views.py:48
#: views.py:43
#, python-format
msgid "Unable to import key id: %s"
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr ""
#: views.py:52
msgid "Import key"
msgstr ""
msgstr "Importar chave"
#: views.py:53
#, python-format
msgid "Are you sure you wish to import key id: %s?"
msgstr ""
msgstr "Você tem certeza que deseja importar chave: %s?"
#: views.py:78
msgid "Key ID"
msgstr ""
msgstr "ID da chave"
#: views.py:82
msgid "Owner"
msgstr ""
msgstr "Proprietário"
#: views.py:102
#, python-format
msgid "Key: %s, deleted successfully."
msgstr ""
msgstr "Chave: %s, apagado com sucesso."
#: views.py:109
msgid "Delete key"
msgstr ""
msgstr "Excluir chave"
#: views.py:111
#, python-format
@@ -192,39 +165,39 @@ msgstr ""
#: views.py:129
msgid "Query key server"
msgstr ""
msgstr "Consultar servidor de chaves"
#: views.py:142
msgid "results"
msgstr ""
msgstr "resultados"
#: views.py:147
msgid "ID"
msgstr ""
msgstr "ID"
#: views.py:151
msgid "type"
msgstr ""
msgstr "tipo"
#: views.py:155
msgid "creation date"
msgstr ""
msgstr "data de criação"
#: views.py:159
msgid "disabled"
msgstr ""
msgstr "desativada"
#: views.py:163
msgid "expiration date"
msgstr ""
msgstr "data de validade"
#: views.py:167
msgid "expired"
msgstr ""
msgstr "expirado"
#: views.py:171
msgid "length"
msgstr ""
msgstr "comprimento"
#: views.py:175
msgid "revoked"
@@ -234,58 +207,10 @@ msgstr ""
msgid "Identifies"
msgstr ""
#: views.py:205
#, python-format
msgid "Signature status: %(widget)s %(text)s"
msgstr ""
#: views.py:212
msgid "embedded"
msgstr ""
#: views.py:214
msgid "detached"
msgstr ""
#: views.py:219
#, python-format
msgid "Signature ID: %s"
msgstr ""
#: views.py:220
#, python-format
msgid "Signature type: %s"
msgstr ""
#: views.py:221
#, python-format
msgid "Key ID: %s"
msgstr ""
#: views.py:222
#, python-format
msgid "Timestamp: %s"
msgstr ""
#: views.py:223
#, python-format
msgid "Signee: %s"
msgstr ""
#: views.py:228
#, python-format
msgid "signature properties for: %s"
msgstr ""
#: views.py:250
msgid "Detached signature uploaded successfully."
msgstr ""
#: views.py:259
#, python-format
msgid "Upload detached signature for: %s"
msgstr ""
#: conf/settings.py:13
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr ""
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr ""

View File

@@ -3,13 +3,14 @@
# This file is distributed under the same license as the PACKAGE package.
#
# Translators:
# Sergey Glita <gsv70@mail.ru>, 2011.
msgid ""
msgstr ""
"Project-Id-Version: Mayan EDMS\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-06 02:06-0400\n"
"PO-Revision-Date: 2011-12-05 17:43+0000\n"
"Last-Translator: rosarior <roberto.rosario.gonzalez@gmail.com>\n"
"POT-Creation-Date: 2012-02-12 15:20-0400\n"
"PO-Revision-Date: 2012-02-02 18:20+0000\n"
"Last-Translator: Roberto Rosario <roberto.rosario.gonzalez@gmail.com>\n"
"Language-Team: Russian (http://www.transifex.net/projects/p/mayan-edms/team/"
"ru/)\n"
"Language: ru\n"
@@ -19,169 +20,141 @@ msgstr ""
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2)\n"
#: __init__.py:14
msgid "Verify document signatures"
msgstr ""
#: __init__.py:14 views.py:67
msgid "private keys"
msgstr "секретные ключи"
#: __init__.py:15
msgid "View keys"
msgstr ""
#: __init__.py:15 views.py:70
msgid "public keys"
msgstr "открытые ключи"
#: __init__.py:16
msgid "Delete keys"
msgstr ""
msgid "delete"
msgstr "удалить"
#: __init__.py:17
msgid "Query keyservers"
msgstr ""
msgid "query keyservers"
msgstr "запрос ключевых серверов"
#: __init__.py:18
msgid "Import key from keyservers"
msgstr ""
msgid "import"
msgstr "получить"
#: __init__.py:19
msgid "Upload detached signatures"
msgstr ""
#: __init__.py:20
msgid "Download detached signatures"
msgstr ""
#: __init__.py:23
msgid "Signatures"
msgstr ""
#: __init__.py:39 views.py:67
msgid "private keys"
msgstr ""
#: __init__.py:40 views.py:70
msgid "public keys"
msgstr ""
#: __init__.py:41
msgid "delete"
msgstr ""
#: __init__.py:42
msgid "query keyservers"
msgstr ""
#: __init__.py:43
msgid "import"
msgstr ""
#: __init__.py:44
msgid "upload signature"
msgstr ""
#: __init__.py:45
msgid "download signature"
msgstr ""
#: __init__.py:46
msgid "key management"
msgstr ""
msgstr "управление ключами"
#: __init__.py:49
msgid "signatures"
msgstr ""
#: api.py:22
#: api.py:19
msgid "Public"
msgstr ""
msgstr "Открытый"
#: api.py:23
#: api.py:20
msgid "Secret"
msgstr ""
msgstr "секретный"
#: api.py:31 api.py:36
#: api.py:28 api.py:33
msgid "RSA"
msgstr ""
msgstr "RSA"
#: api.py:32
#: api.py:29
msgid "DSA"
msgstr ""
msgstr "DSA"
#: api.py:37
#: api.py:34
msgid "Elgamal"
msgstr ""
msgstr "Elgamal"
#: api.py:51
#: api.py:48
msgid "Bad signature."
msgstr ""
msgstr "Неверная подпись"
#: api.py:55
#: api.py:52
msgid "Document not signed or invalid signature."
msgstr ""
msgstr "Документ не подписан, либо подпись неверна."
#: api.py:59
#: api.py:56
msgid "Signature error."
msgstr ""
msgstr "Ошибка подписи."
#: api.py:63
#: api.py:60
msgid "Document is signed but no public key is available for verification."
msgstr ""
msgstr "Документ подписан, но нет открытого ключа для проверки."
#: api.py:67
#: api.py:64
msgid "Document is signed, and signature is good."
msgstr ""
msgstr "Документ подписан и подпись верна."
#: api.py:71
#: api.py:68
msgid "Document is signed with a valid signature."
msgstr ""
msgstr "Документ подписан допустимой подписью."
#: api.py:144
#: api.py:141
msgid "unknown"
msgstr ""
msgstr "неизвестно"
#: forms.py:11
#: forms.py:8
msgid "Term"
msgstr ""
msgstr "Term"
#: forms.py:12
#: forms.py:9
msgid "Name, e-mail, key ID or key fingerprint to look for."
msgstr "Имя, e-mail, ID ключа или отпечаток для поиска."
#: permissions.py:7
msgid "Key management"
msgstr ""
#: forms.py:18
msgid "Signature file"
#: permissions.py:9
msgid "View keys"
msgstr "Просмотр ключей"
#: permissions.py:10
msgid "Delete keys"
msgstr "Удалить ключи"
#: permissions.py:11
msgid "Query keyservers"
msgstr "Запрос к серверам ключей"
#: permissions.py:12
msgid "Import keys from keyservers"
msgstr ""
#: views.py:45
#: views.py:38
#, python-format
msgid "Key: %s, imported successfully."
msgstr ""
msgstr "Ключ %s, получен."
#: views.py:48
#: views.py:43
#, python-format
msgid "Unable to import key id: %s"
msgid "Unable to import key id: %(key_id)s; %(error)s"
msgstr ""
#: views.py:52
msgid "Import key"
msgstr ""
msgstr "Получить ключ"
#: views.py:53
#, python-format
msgid "Are you sure you wish to import key id: %s?"
msgstr ""
msgstr "Хотите получить ключ id: %s?"
#: views.py:78
msgid "Key ID"
msgstr ""
msgstr "ID ключа"
#: views.py:82
msgid "Owner"
msgstr ""
msgstr "Владелец"
#: views.py:102
#, python-format
msgid "Key: %s, deleted successfully."
msgstr ""
msgstr "Ключ %s удалён."
#: views.py:109
msgid "Delete key"
msgstr ""
msgstr "Удалить ключ."
#: views.py:111
#, python-format
@@ -190,103 +163,57 @@ msgid ""
"that is part of a public/private pair the private key will be deleted as "
"well."
msgstr ""
"Вы уверены, что хотите удалить ключ %s? Если вы удалите открытый ключ то "
"соответствующий ему закрытый ключ тоже будет удалён."
#: views.py:129
msgid "Query key server"
msgstr ""
msgstr "Запросить сервер ключей"
#: views.py:142
msgid "results"
msgstr ""
msgstr "результаты"
#: views.py:147
msgid "ID"
msgstr ""
msgstr "ID"
#: views.py:151
msgid "type"
msgstr ""
msgstr "тип"
#: views.py:155
msgid "creation date"
msgstr ""
msgstr "дата создания"
#: views.py:159
msgid "disabled"
msgstr ""
msgstr "запрещено"
#: views.py:163
msgid "expiration date"
msgstr ""
msgstr "дата окончания"
#: views.py:167
msgid "expired"
msgstr ""
msgstr "истекло"
#: views.py:171
msgid "length"
msgstr ""
msgstr "длина"
#: views.py:175
msgid "revoked"
msgstr ""
msgstr "отозван"
#: views.py:180
msgid "Identifies"
msgstr ""
msgstr "Identifies"
#: views.py:205
#, python-format
msgid "Signature status: %(widget)s %(text)s"
msgstr ""
#: views.py:212
msgid "embedded"
msgstr ""
#: views.py:214
msgid "detached"
msgstr ""
#: views.py:219
#, python-format
msgid "Signature ID: %s"
msgstr ""
#: views.py:220
#, python-format
msgid "Signature type: %s"
msgstr ""
#: views.py:221
#, python-format
msgid "Key ID: %s"
msgstr ""
#: views.py:222
#, python-format
msgid "Timestamp: %s"
msgstr ""
#: views.py:223
#, python-format
msgid "Signee: %s"
msgstr ""
#: views.py:228
#, python-format
msgid "signature properties for: %s"
msgstr ""
#: views.py:250
msgid "Detached signature uploaded successfully."
msgstr ""
#: views.py:259
#, python-format
msgid "Upload detached signature for: %s"
msgstr ""
#: conf/settings.py:13
#: conf/settings.py:15
msgid "List of keyservers to be queried for unknown keys."
msgstr "Список ключевых серверов для запроса неизвестных ключей."
#: conf/settings.py:16
msgid "Home directory used to store keys as well as configuration files."
msgstr ""

View File

@@ -1 +0,0 @@

View File

@@ -0,0 +1,12 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from permissions.models import PermissionNamespace, Permission
django_gpg_namespace = PermissionNamespace('django_gpg', _(u'Key management'))
PERMISSION_KEY_VIEW = Permission.objects.register(django_gpg_namespace, 'key_view', _(u'View keys'))
PERMISSION_KEY_DELETE = Permission.objects.register(django_gpg_namespace, 'key_delete', _(u'Delete keys'))
PERMISSION_KEYSERVER_QUERY = Permission.objects.register(django_gpg_namespace, 'keyserver_query', _(u'Query keyservers'))
PERMISSION_KEY_RECEIVE = Permission.objects.register(django_gpg_namespace, 'key_receive', _(u'Import keys from keyservers'))

View File

@@ -1,4 +1,13 @@
from django_gpg.api import GPG
from django_gpg.conf.settings import KEYSERVERS
from __future__ import absolute_import
gpg = GPG(keyservers=KEYSERVERS)
import sys
from .api import GPG
from .conf.settings import KEYSERVERS, GPG_HOME
try:
gpg = GPG(home=GPG_HOME, keyservers=KEYSERVERS)
except Exception, e:
gpg = GPG(keyservers=KEYSERVERS)
sys.stderr.write(u'ERROR: GPG initialization error: %s\n' % e)
sys.stderr.write(u'INFO: Initializating GPG with system default home\n')

View File

@@ -4,9 +4,6 @@ urlpatterns = patterns('django_gpg.views',
url(r'^delete/(?P<fingerprint>.+)/(?P<key_type>\w+)/$', 'key_delete', (), 'key_delete'),
url(r'^list/private/$', 'key_list', {'secret': True}, 'key_private_list'),
url(r'^list/public/$', 'key_list', {'secret': False}, 'key_public_list'),
url(r'^verify/(?P<document_pk>\d+)/$', 'document_verify', (), 'document_verify'),
url(r'^upload/signature/(?P<document_pk>\d+)/$', 'document_signature_upload', (), 'document_signature_upload'),
url(r'^download/signature/(?P<document_pk>\d+)/$', 'document_signature_download', (), 'document_signature_download'),
url(r'^query/$', 'key_query', (), 'key_query'),
url(r'^receive/(?P<key_id>.+)/$', 'key_receive', (), 'key_receive'),
)

View File

@@ -1,38 +1,29 @@
from datetime import datetime
from __future__ import absolute_import
import logging
from django.utils.translation import ugettext_lazy as _
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.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 documents.models import Document, RecentDocument
from permissions.api import check_permissions
from common.utils import pretty_size, parse_range, urlquote, \
return_diff, encapsulate
from filetransfers.api import serve_file
from django_gpg.api import Key, SIGNATURE_STATES
from django_gpg.runtime import gpg
from django_gpg.exceptions import (GPGVerificationError, KeyFetchingError,
KeyImportError)
from django_gpg import (PERMISSION_DOCUMENT_VERIFY, PERMISSION_KEY_VIEW,
PERMISSION_KEY_DELETE, PERMISSION_KEYSERVER_QUERY,
PERMISSION_KEY_RECEIVE, PERMISSION_SIGNATURE_UPLOAD,
PERMISSION_SIGNATURE_DOWNLOAD)
from django_gpg.forms import KeySearchForm, DetachedSignatureForm
from permissions.models import Permission
from common.utils import encapsulate
from .api import Key
from .runtime import gpg
from .exceptions import KeyFetchingError, KeyImportError
from .forms import KeySearchForm
from .permissions import (PERMISSION_KEY_VIEW, PERMISSION_KEY_DELETE,
PERMISSION_KEYSERVER_QUERY, PERMISSION_KEY_RECEIVE)
logger = logging.getLogger(__name__)
def key_receive(request, key_id):
check_permissions(request.user, [PERMISSION_KEY_RECEIVE])
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_RECEIVE])
post_action_redirect = None
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', '/')))
@@ -45,8 +36,15 @@ def key_receive(request, key_id):
key = gpg.import_key(keys_dict[key_id].key)
messages.success(request, _(u'Key: %s, imported successfully.') % key)
return HttpResponseRedirect(next)
except (KeyImportError, KeyError, TypeError):
messages.error(request, _(u'Unable to import key id: %s') % key_id)
except (KeyImportError, KeyError, TypeError), e:
messages.error(
request,
_(u'Unable to import key id: %(key_id)s; %(error)s') %
{
'key_id': key_id,
'error': e,
}
)
return HttpResponseRedirect(previous)
return render_to_response('generic_confirm.html', {
@@ -56,13 +54,13 @@ def key_receive(request, key_id):
'next': next,
'previous': previous,
'submit_method': 'GET',
}, context_instance=RequestContext(request))
def key_list(request, secret=True):
check_permissions(request.user, [PERMISSION_KEY_VIEW])
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_VIEW])
if secret:
object_list = Key.get_all(gpg, secret=True)
title = _(u'private keys')
@@ -88,8 +86,8 @@ def key_list(request, secret=True):
def key_delete(request, fingerprint, key_type):
check_permissions(request.user, [PERMISSION_KEY_DELETE])
Permission.objects.check_permissions(request.user, [PERMISSION_KEY_DELETE])
secret = key_type == 'sec'
key = Key.get(gpg, fingerprint, secret=secret)
@@ -117,8 +115,8 @@ def key_delete(request, fingerprint, key_type):
def key_query(request):
check_permissions(request.user, [PERMISSION_KEYSERVER_QUERY])
Permission.objects.check_permissions(request.user, [PERMISSION_KEYSERVER_QUERY])
subtemplates_list = []
term = request.GET.get('term')
@@ -132,8 +130,8 @@ def key_query(request):
'submit_method': 'GET',
},
}
)
)
if term:
results = gpg.query(term)
subtemplates_list.append(
@@ -155,132 +153,37 @@ def key_query(request):
{
'name': _(u'creation date'),
'attribute': 'creation_date',
},
},
{
'name': _(u'disabled'),
'attribute': 'disabled',
},
},
{
'name': _(u'expiration date'),
'attribute': 'expiration_date',
},
},
{
'name': _(u'expired'),
'attribute': 'expired',
},
},
{
'name': _(u'length'),
'attribute': 'key_length',
},
},
{
'name': _(u'revoked'),
'attribute': 'revoked',
},
},
{
'name': _(u'Identifies'),
'attribute': encapsulate(lambda x: u', '.join([identity.uid for identity in x.identities])),
},
]
]
},
}
)
)
return render_to_response('generic_form.html', {
'subtemplates_list': subtemplates_list,
}, context_instance=RequestContext(request))
def document_verify(request, document_pk):
check_permissions(request.user, [PERMISSION_DOCUMENT_VERIFY])
document = get_object_or_404(Document, pk=document_pk)
RecentDocument.objects.add_document_for_user(request.user, document)
signature = document.verify_signature()
signature_state = SIGNATURE_STATES.get(getattr(signature, 'status', None))
widget = (u'<img style="vertical-align: middle;" src="%simages/icons/%s" />' % (settings.STATIC_URL, signature_state['icon']))
paragraphs = [
_(u'Signature status: %(widget)s %(text)s') % {
'widget': mark_safe(widget),
'text': signature_state['text']
},
]
if document.signature_state:
signature_type = _(u'embedded')
else:
signature_type = _(u'detached')
if signature:
paragraphs.extend(
[
_(u'Signature ID: %s') % signature.signature_id,
_(u'Signature type: %s') % signature_type,
_(u'Key ID: %s') % signature.key_id,
_(u'Timestamp: %s') % datetime.fromtimestamp(int(signature.sig_timestamp)),
_(u'Signee: %s') % force_escape(getattr(signature, 'username', u'')),
]
)
return render_to_response('generic_template.html', {
'title': _(u'signature properties for: %s') % document,
'object': document,
'document': document,
'paragraphs': paragraphs,
}, context_instance=RequestContext(request))
def document_signature_upload(request, document_pk):
check_permissions(request.user, [PERMISSION_SIGNATURE_UPLOAD])
document = get_object_or_404(Document, pk=document_pk)
RecentDocument.objects.add_document_for_user(request.user, document)
post_action_redirect = None
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', '/')))
if request.method == 'POST':
form = DetachedSignatureForm(request.POST, request.FILES)
if form.is_valid():
try:
document.add_detached_signature(request.FILES['file'])
messages.success(request, _(u'Detached signature uploaded successfully.'))
return HttpResponseRedirect(next)
except Exception, msg:
messages.error(request, msg)
return HttpResponseRedirect(previous)
else:
form = DetachedSignatureForm()
return render_to_response('generic_form.html', {
'title': _(u'Upload detached signature for: %s') % document,
'form_icon': 'key_delete.png',
'next': next,
'form': form,
'previous': previous,
'object': document,
}, context_instance=RequestContext(request))
def document_signature_download(request, document_pk):
check_permissions(request.user, [PERMISSION_SIGNATURE_DOWNLOAD])
document = get_object_or_404(Document, pk=document_pk)
try:
if document.has_detached_signature():
signature = document.detached_signature()
return serve_file(
request,
signature,
save_as=u'"%s.sig"' % document.filename,
content_type=u'application/octet-stream'
)
except Exception, e:
messages.error(request, e)
return HttpResponseRedirect(request.META['HTTP_REFERER'])
return HttpResponseRedirect(request.META['HTTP_REFERER'])

View File

@@ -0,0 +1,15 @@
from django.utils.translation import ugettext_lazy as _
from documents.models import Document
from navigation.api import register_links
from acls import ACLS_VIEW_ACL, ACLS_EDIT_ACL
from acls.api import class_permissions
acl_list = {'text': _(u'ACLs'), 'view': 'document_acl_list', 'args': 'object.pk', 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
register_links(Document, [acl_list], menu_name='form_header')
class_permissions(Document, [
ACLS_VIEW_ACL,
ACLS_EDIT_ACL
])

View File

@@ -0,0 +1,5 @@
from django.conf.urls.defaults import patterns, url
urlpatterns = patterns('document_acls.views',
url(r'^list_for/document/(?P<document_id>\d+)/$', 'document_acl_list', (), 'document_acl_list'),
)

View File

@@ -0,0 +1,16 @@
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext_lazy as _
from documents.models import Document
from acls.views import acl_list_for
def document_acl_list(request, document_id):
document = get_object_or_404(Document, pk=document_id)
return acl_list_for(
request,
document,
extra_context={
'object': document,
}
)

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