Merge branch 'feature/anonymous_support' into development

This commit is contained in:
Roberto Rosario
2012-01-08 04:59:42 -04:00
30 changed files with 283 additions and 123 deletions

View File

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

View File

@@ -15,11 +15,11 @@ acl_detail = {'text': _(u'details'), 'view': 'acl_detail', 'args': ['access_obje
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_setup_valid_classes = {'text': _(u'Default ACLs'), 'view': 'acl_setup_valid_classes', 'icon': 'lock.png'}#, 'permissions': [ACLS_EDIT_ACL]}
acl_class_list = {'text': _(u'List of classes'), 'view': 'acl_setup_valid_classes', 'famfam': 'package'}#, 'permissions': [ACLS_EDIT_ACL]}
acl_class_acl_list = {'text': _(u'ACLs for class'), 'view': 'acl_class_acl_list', 'args': 'object.gid', 'famfam': 'lock'}#, 'permissions': [ACLS_VIEW_ACL]}
acls_class_acl_detail = {'text': _(u'edit'), 'view': 'acls_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'lock', 'permissions': [ACLS_VIEW_ACL]}
acl_class_new_holder_for = {'text': _(u'New holder'), 'view': 'acl_class_new_holder_for', 'args': 'object.gid', 'famfam': 'user'}#, 'permissions': [ACLS_VIEW_ACL]}
acl_setup_valid_classes = {'text': _(u'Default ACLs'), 'view': 'acl_setup_valid_classes', 'icon': 'lock.png', 'permissions': [ACLS_CLASS_VIEW_ACL]}
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', 'permissions': [ACLS_CLASS_VIEW_ACL]}
acl_class_acl_detail = {'text': _(u'edit'), 'view': 'acls_class_acl_detail', 'args': ['access_object_class.gid', 'object.gid'], 'famfam': 'lock', '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]}
@@ -27,9 +27,9 @@ register_links(AccessHolder, [acl_detail])
register_multi_item_links(['acl_detail'], [acl_grant, acl_revoke])
register_setup(acl_setup_valid_classes)
register_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acls_class_acl_detail'], [acl_class_list], menu_name='sidebar')
register_links(['acl_setup_valid_classes', 'acl_class_acl_list', 'acl_class_new_holder_for', 'acl_class_acl_detail'], [acl_class_list], menu_name='sidebar')
register_links(ClassAccessHolder, [acls_class_acl_detail])
register_links(ClassAccessHolder, [acl_class_acl_detail])
register_links(AccessObjectClass, [acl_class_acl_list])
register_links(AccessObjectClass, [acl_class_new_holder_for])

View File

@@ -2,9 +2,12 @@ import logging
import sys
import types
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.db.models.base import ModelBase
from common.models import AnonymousUserSingleton
logger = logging.getLogger(__name__)
_cache = {}
@@ -27,6 +30,7 @@ class EncapsulatedObject(object):
@classmethod
def encapsulate(cls, source_object=None, app_label=None, model=None, pk=None):
if source_object:
source_object = AnonymousUserSingleton.objects.passthru_check(source_object)
content_type = ContentType.objects.get_for_model(source_object)
elif app_label and model:
try:

View File

@@ -6,6 +6,7 @@ from django.contrib.auth.models import User, Group
from permissions.models import Permission, Role
from common.utils import generate_choices_w_labels, encapsulate, get_object_name
from common.models import AnonymousUserSingleton
from .classes import AccessHolder
@@ -39,5 +40,7 @@ class HolderSelectionForm(forms.Form):
if roles:
non_holder_list.append((_(u'Roles'), _as_choice_list(list(roles))))
non_holder_list.append((_(u'Special'), _as_choice_list([AnonymousUserSingleton.get()])))
super(HolderSelectionForm, self).__init__(*args, **kwargs)
self.fields['holder_gid'].choices = non_holder_list

View File

@@ -9,6 +9,8 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from common.models import AnonymousUserSingleton
from .classes import EncapsulatedObject, AccessHolder, ClassAccessHolder
logger = logging.getLogger(__name__)
@@ -65,6 +67,8 @@ class AccessEntryManager(models.Manager):
if actor.is_superuser or actor.is_staff:
return True
actor = AnonymousUserSingleton.objects.passthru_check(actor)
try:
access_entry = self.model.objects.get(
permission=permission.get_stored_permission(),
@@ -97,7 +101,8 @@ class AccessEntryManager(models.Manager):
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)
if related:

View File

@@ -19,7 +19,7 @@ from .managers import AccessEntryManager, DefaultAccessEntryManager
logger = logging.getLogger(__name__)
class AccessEntry(models.Model):
'''
Model that hold the permission, object, actor relationship

View File

@@ -50,8 +50,6 @@ def acl_list_for(request, obj, extra_context=None):
context = {
'object_list': AccessEntry.objects.get_holders_for(obj),
'title': _(u'access control lists for: %s' % obj),
#'multi_select_as_buttons': True,
#'hide_links': True,
'extra_columns': [
{'name': _(u'holder'), 'attribute': encapsulate(lambda x: object_w_content_type_icon(x.source_object))},
{'name': _(u'permissions'), 'attribute': encapsulate(lambda x: _permission_titles(AccessEntry.objects.get_holder_permissions_for(obj, x.source_object)))},

View File

@@ -6,6 +6,8 @@ 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
@@ -31,34 +33,31 @@ register_links(['about_view', 'changelog_view', 'license_view'], [about_view, ch
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

@@ -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,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,43 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
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()
class Meta:
verbose_name = _(u'anonymous user')
verbose_name_plural = _(u'anonymous user')

View File

@@ -0,0 +1,30 @@
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,4 +1,4 @@
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import os
import re
import types
@@ -13,6 +13,7 @@ from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.contrib.auth.models import AnonymousUser
def urlquote(link=None, get=None):
@@ -333,9 +334,15 @@ def get_object_name(obj, display_object_type=True):
label = unicode(obj)
if isinstance(obj, User):
label = obj.get_full_name() if obj.get_full_name() else obj
elif isinstance(obj, AnonymousUser):
label = _(u'Anonymous user')
if display_object_type:
verbose_name = unicode(getattr(obj._meta, u'verbose_name', ct_label))
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)

View File

@@ -193,8 +193,13 @@ def login_view(request):
if LOGIN_METHOD == 'email':
kwargs['authentication_form'] = EmailAuthenticationForm
if not request.user.is_authenticated():
context = {'web_theme_view_type': 'plain'}
else:
context = {}
return login(request, **kwargs)
return login(request, extra_context=context, **kwargs)
def changelog_view(request):

View File

@@ -9,7 +9,6 @@ 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 tags.widgets import get_tags_inline_widget_simple
from history.api import register_history_type
from history.permissions import PERMISSION_HISTORY_VIEW
from metadata.api import get_metadata_string
@@ -168,9 +167,6 @@ register_model_list_columns(Document, [
{'name':_(u'thumbnail'), 'attribute':
encapsulate(lambda x: document_thumbnail(x))
},
{'name':_(u'tags'), 'attribute':
encapsulate(lambda x: get_tags_inline_widget_simple(x))
},
{'name':_(u'metadata'), 'attribute':
encapsulate(lambda x: get_metadata_string(x))
},

View File

@@ -4,6 +4,7 @@ from ast import literal_eval
from datetime import datetime
from django.db import models
from django.contrib.auth.models import AnonymousUser
from .conf.settings import RECENT_COUNT
@@ -16,6 +17,12 @@ class RecentDocumentManager(models.Manager):
to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:]
for recent_to_delete in to_delete:
recent_to_delete.delete()
def get_for_user(self, user):
if not user.is_anonymous():
return [recent_document.document for recent_document in self.model.objects.filter(user=user)]
else:
return []
class DocumentPageTransformationManager(models.Manager):

View File

@@ -827,7 +827,7 @@ def document_page_navigation_last(request, document_page_id):
def document_list_recent(request):
return document_list(
request,
object_list=[recent_document.document for recent_document in RecentDocument.objects.filter(user=request.user)],
object_list=RecentDocument.objects.get_for_user(request.user),
title=_(u'recent documents'),
extra_context={
'recent_count': RECENT_COUNT

View File

@@ -2,7 +2,8 @@ import urlparse
from django.db import models
from django.utils.http import urlencode
from django.contrib.auth.models import AnonymousUser
from dynamic_search.conf.settings import RECENT_COUNT
@@ -21,7 +22,7 @@ class RecentSearchManager(models.Manager):
# Cleanup query string and only store the q parameter
parsed_query = {'q': parsed_query['q']}
if parsed_query:
if parsed_query and not isinstance(user, AnonymousUser):
# If the URL query has at least one variable with a value
new_recent, created = self.model.objects.get_or_create(user=user, query=urlencode(parsed_query), defaults={'hits': hits})
new_recent.hits = hits

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
from django.utils.translation import ugettext_lazy as _
from django.conf import settings
from navigation.api import register_top_menu
from navigation.api import register_links
@@ -55,8 +56,12 @@ def get_version():
__version__ = get_version()
register_setup(admin_site)
if 'django.contrib.admin' in settings.INSTALLED_APPS:
register_setup(admin_site)
register_tool(maintenance_menu)
register_tool(statistics)
register_tool(diagnostics)
register_tool(sentry)
if 'sentry' in settings.INSTALLED_APPS:
register_tool(sentry)

View File

@@ -181,7 +181,7 @@
{% block web_theme_user_navigation %}
<li><strong>{% trans "User" %}:</strong>
{% if user.is_anonymous %}
{% if not user.is_authenticated %}
{% trans "Anonymous" %}
{% else %}
{{ user.get_full_name|default:user }}
@@ -202,7 +202,7 @@
</li>
{% endif %}
{% get_setting "LOGIN_URL" as login_url %}
<li><a class="logout" href="{% if user.is_anonymous %}{% url login_view %}?next=/{% else %}{% url logout_view %}?next={{ login_url }}{% endif %}">{% if user.is_anonymous %}{% trans "Login" %}{% else %}{% trans "Logout" %}{% endif %}</a></li>
<li><a class="logout" href="{% if not user.is_authenticated %}{% url login_view %}?next=/{% else %}{% url logout_view %}{% endif %}">{% if not user.is_authenticated %}{% trans "Login" %}{% else %}{% trans "Logout" %}{% endif %}</a></li>
{% endblock %}
{% block web_theme_main_navigation %}

View File

@@ -8,11 +8,15 @@ from django.shortcuts import get_object_or_404
from django.db.utils import IntegrityError
from django.core.exceptions import ImproperlyConfigured
from common.models import AnonymousUserSingleton
logger = logging.getLogger(__name__)
class RoleMemberManager(models.Manager):
def get_roles_for_member(self, member_obj):
member_obj = AnonymousUserSingleton.objects.passthru_check(member_obj)
member_type = ContentType.objects.get_for_model(member_obj)
return [role_member.role for role_member in self.model.objects.filter(member_type=member_type, member_id=member_obj.pk)]

View File

@@ -10,6 +10,8 @@ from django.contrib.contenttypes import generic
from django.contrib.auth.models import User
from django.core.exceptions import PermissionDenied
from common.models import AnonymousUserSingleton
from .managers import (RoleMemberManager, StoredPermissionManager)
logger = logging.getLogger(__name__)
@@ -44,6 +46,8 @@ class PermissionManager(object):
if permission.requester_has_this(requester):
return True
logger.debug('no permission')
raise PermissionDenied(ugettext(u'Insufficient permissions.'))
@classmethod
@@ -105,8 +109,7 @@ class Permission(object):
return stored_permission
def requester_has_this(self, requester):
stored_permission = self.get_stored_permission(
)
stored_permission = self.get_stored_permission()
return stored_permission.requester_has_this(requester)
def save(self, *args, **kwargs):
@@ -139,6 +142,8 @@ class StoredPermission(models.Model):
return [holder.holder_object for holder in self.permissionholder_set.all()]
def requester_has_this(self, requester):
requester = AnonymousUserSingleton.objects.passthru_check(requester)
logger.debug('requester: %s' % requester)
if isinstance(requester, User):
if requester.is_superuser or requester.is_staff:
return True
@@ -159,12 +164,17 @@ class StoredPermission(models.Model):
for membership in list(set(roles) | set(groups)):
if self.requester_has_this(membership):
return True
logger.debug('Fallthru')
return False
def grant_to(self, requester):
requester = AnonymousUserSingleton.objects.passthru_check(requester)
permission_holder, created = PermissionHolder.objects.get_or_create(permission=self, holder_type=ContentType.objects.get_for_model(requester), holder_id=requester.pk)
return created
def revoke_from(self, holder):
requester = AnonymousUserSingleton.objects.passthru_check(requester)
try:
permission_holder = PermissionHolder.objects.get(permission=self, holder_type=ContentType.objects.get_for_model(holder), holder_id=holder.pk)
permission_holder.delete()
@@ -199,6 +209,7 @@ class Role(models.Model):
verbose_name_plural = _(u'roles')
def add_member(self, member):
member = AnonymousUserSingleton.objects.passthru_check(member)
role_member, created = RoleMember.objects.get_or_create(
role=self,
member_type=ContentType.objects.get_for_model(member),

View File

@@ -1,6 +1,5 @@
from django.core.exceptions import PermissionDenied
from django.template import TemplateSyntaxError, Library, \
Node, Variable
from django.template import TemplateSyntaxError, Library, Node, Variable
from permissions.models import Permission

View File

@@ -23,21 +23,21 @@ from .permissions import (PERMISSION_SOURCES_SETUP_VIEW,
staging_file_preview = {'text': _(u'preview'), 'class': 'fancybox-noscaling', 'view': 'staging_file_preview', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'zoom'}
staging_file_delete = {'text': _(u'delete'), 'view': 'staging_file_delete', 'args': ['source.source_type', 'source.pk', 'object.id'], 'famfam': 'delete', 'keep_query': True}
setup_sources = {'text': _(u'sources'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'icon': 'application_form.png', 'children_classes': [WebForm]}
setup_web_form_list = {'text': _(u'web forms'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'icon': 'application_form.png', 'children_classes': [WebForm]}
setup_staging_folder_list = {'text': _(u'staging folders'), 'view': 'setup_staging_folder_list', 'famfam': 'folder_camera', 'children_classes': [StagingFolder]}
setup_watch_folder_list = {'text': _(u'watch folders'), 'view': 'setup_watch_folder_list', 'famfam': 'folder_magnify', 'children_classes': [WatchFolder]}
setup_sources = {'text': _(u'sources'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'icon': 'application_form.png', 'children_classes': [WebForm], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]}
setup_web_form_list = {'text': _(u'web forms'), 'view': 'setup_web_form_list', 'famfam': 'application_form', 'icon': 'application_form.png', 'children_classes': [WebForm], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]}
setup_staging_folder_list = {'text': _(u'staging folders'), 'view': 'setup_staging_folder_list', 'famfam': 'folder_camera', 'children_classes': [StagingFolder], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]}
setup_watch_folder_list = {'text': _(u'watch folders'), 'view': 'setup_watch_folder_list', 'famfam': 'folder_magnify', 'children_classes': [WatchFolder], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]}
setup_source_edit = {'text': _(u'edit'), 'view': 'setup_source_edit', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_edit'}
setup_source_delete = {'text': _(u'delete'), 'view': 'setup_source_delete', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_delete'}
setup_source_create = {'text': _(u'add new source'), 'view': 'setup_source_create', 'args': 'source_type', 'famfam': 'application_form_add'}
setup_source_edit = {'text': _(u'edit'), 'view': 'setup_source_edit', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_edit', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]}
setup_source_delete = {'text': _(u'delete'), 'view': 'setup_source_delete', 'args': ['source.source_type', 'source.pk'], 'famfam': 'application_form_delete', 'permissions': [PERMISSION_SOURCES_SETUP_DELETE]}
setup_source_create = {'text': _(u'add new source'), 'view': 'setup_source_create', 'args': 'source_type', 'famfam': 'application_form_add', 'permissions': [PERMISSION_SOURCES_SETUP_CREATE]}
setup_source_transformation_list = {'text': _(u'transformations'), 'view': 'setup_source_transformation_list', 'args': ['source.source_type', 'source.pk'], 'famfam': 'shape_move_front'}
setup_source_transformation_create = {'text': _(u'add transformation'), 'view': 'setup_source_transformation_create', 'args': ['source.source_type', 'source.pk'], 'famfam': 'shape_square_add'}
setup_source_transformation_edit = {'text': _(u'edit'), 'view': 'setup_source_transformation_edit', 'args': 'transformation.pk', 'famfam': 'shape_square_edit'}
setup_source_transformation_delete = {'text': _(u'delete'), 'view': 'setup_source_transformation_delete', 'args': 'transformation.pk', 'famfam': 'shape_square_delete'}
setup_source_transformation_list = {'text': _(u'transformations'), 'view': 'setup_source_transformation_list', 'args': ['source.source_type', 'source.pk'], 'famfam': 'shape_move_front', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]}
setup_source_transformation_create = {'text': _(u'add transformation'), 'view': 'setup_source_transformation_create', 'args': ['source.source_type', 'source.pk'], 'famfam': 'shape_square_add', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]}
setup_source_transformation_edit = {'text': _(u'edit'), 'view': 'setup_source_transformation_edit', 'args': 'transformation.pk', 'famfam': 'shape_square_edit', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]}
setup_source_transformation_delete = {'text': _(u'delete'), 'view': 'setup_source_transformation_delete', 'args': 'transformation.pk', 'famfam': 'shape_square_delete', 'permissions': [PERMISSION_SOURCES_SETUP_EDIT]}
source_list = {'text': _(u'Document sources'), 'view': 'setup_web_form_list', 'famfam': 'page_add', 'children_url_regex': [r'sources/setup']}
source_list = {'text': _(u'Document sources'), 'view': 'setup_web_form_list', 'famfam': 'page_add', 'children_url_regex': [r'sources/setup'], 'permissions': [PERMISSION_SOURCES_SETUP_VIEW]}
upload_version = {'text': _(u'upload new version'), 'view': 'upload_version', 'args': 'object.pk', 'famfam': 'page_add', 'permissions': [PERMISSION_DOCUMENT_NEW_VERSION]}

View File

@@ -12,14 +12,15 @@ from acls.permissions import ACLS_VIEW_ACL
from taggit.models import Tag
from taggit.managers import TaggableManager
from .widgets import get_tags_inline_widget_simple
from .widgets import tag_color_block
from .permissions import (PERMISSION_TAG_CREATE, PERMISSION_TAG_ATTACH,
PERMISSION_TAG_REMOVE, PERMISSION_TAG_DELETE, PERMISSION_TAG_EDIT,
PERMISSION_TAG_VIEW)
tag_list = {'text': _(u'tag list'), 'view': 'tag_list', 'famfam': 'tag_blue'}
tag_create = {'text': _(u'create new tag'), 'view': 'tag_create', 'famfam': 'tag_blue_add', 'permission': [PERMISSION_TAG_CREATE]}
tag_attach = {'text': _(u'attach tag'), 'view': 'tag_attach', 'args': 'object.pk', 'famfam': 'tag_blue_add', 'permission': [PERMISSION_TAG_ATTACH]}
tag_create = {'text': _(u'create new tag'), 'view': 'tag_create', 'famfam': 'tag_blue_add', 'permissions': [PERMISSION_TAG_CREATE]}
tag_attach = {'text': _(u'attach tag'), 'view': 'tag_attach', 'args': 'object.pk', 'famfam': 'tag_blue_add', 'permissions': [PERMISSION_TAG_ATTACH]}
tag_document_remove = {'text': _(u'remove'), 'view': 'tag_remove', 'args': ['object.id', 'document.id'], 'famfam': 'tag_blue_delete', 'permissions': [PERMISSION_TAG_REMOVE]}
tag_document_remove_multiple = {'text': _(u'remove'), 'view': 'tag_multiple_remove', 'args': 'document.id', 'famfam': 'tag_blue_delete', 'permissions': [PERMISSION_TAG_REMOVE]}
tag_document_list = {'text': _(u'tags'), 'view': 'document_tags', 'args': 'object.pk', 'famfam': 'tag_blue', 'permissions': [PERMISSION_TAG_REMOVE, PERMISSION_TAG_ATTACH], 'children_view_regex': ['tag']}
@@ -45,6 +46,12 @@ register_model_list_columns(Tag, [
}
])
register_model_list_columns(Document, [
{'name':_(u'tags'), 'attribute':
encapsulate(lambda x: get_tags_inline_widget_simple(x))
},
])
register_links(Tag, [tag_tagged_item_list, tag_edit, tag_delete, tag_acl_list])
register_multi_item_links(['tag_list'], [tag_multiple_delete])
register_links([Tag, 'tag_list', 'tag_create'], [tag_list, tag_create], menu_name='secondary_menu')

View File

@@ -69,7 +69,7 @@
</head>
<body>
<div id="container">
{% if user.is_anonymous %}
{% if web_theme_view_type == 'plain' %}
<div id="box">
{% block content_plain %}{% endblock %}
</div>

View File

@@ -3,51 +3,52 @@
{% load theme_tags %}
{% block web_theme_head %}
{% if not user.is_anonymous %}
{% if user.is_authenticated %}
{% get_login_redirect_url %}
<meta http-equiv="REFRESH" content="5;url={{ LOGIN_REDIRECT_URL }}">
{% endif %}
{% endblock %}
{% block html_title %}{% trans "Login" %}{% endblock %}
{% if not user.is_anonymous %}
{% block web_theme_content %}
{% get_login_redirect_url %}
<div class="content">
<h2 class="title">{% trans "You are already logged in" %}</h2>
<div class="inner">
<p>
{% trans "Redirecting you to the website entry point in 5 seconds." %}
<p>
</p>
{% blocktrans %}Or click <a href="{{ LOGIN_REDIRECT_URL }}">here</a> if redirection doesn't work.{% endblocktrans %}
</p>
</div>
</div>
{% endblock %}
{% else %}
{% block content_plain %}
<div id="box">
<h1>{% block project_name %}{% endblock %}</h1>
<div class="block" id="block-login">
<h2>{% trans "Login" %}</h2>
<div class="content login">
<form action="." method="post" class="form login">{% csrf_token %}
<div class="group wat-cf">
{% include "generic_form_instance.html" %}
<input type="hidden" name="next" value="{{ next|escape }}" />
<div class="group navform wat-cf">
<button class="button" type="submit">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/key.png" alt="Save" /> Login
</button>
</div>
</form>
{% if user.is_authenticated %}
{% block web_theme_content %}
{% get_login_redirect_url %}
<div class="content">
<h2 class="title">{% trans "You are already logged in" %}</h2>
<div class="inner">
<p>
{% trans "Redirecting you to the website entry point in 5 seconds." %}
<p>
</p>
{% blocktrans %}Or click <a href="{{ LOGIN_REDIRECT_URL }}">here</a> if redirection doesn't work.{% endblocktrans %}
</p>
</div>
</div>
</div>
</div>
{% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %}
{% if verbose_login %}
{% include "verbose_login.html" %}
{% endif %}
{% endblock %}
{% endif %}
{% endblock %}
{% else %}
{% block content_plain %}
<div id="box">
<h1>{% block project_name %}{% endblock %}</h1>
<div class="block" id="block-login">
<h2>{% trans "Login" %}</h2>
<div class="content login">
<form action="." method="post" class="form login">{% csrf_token %}
<div class="group wat-cf">
{% include "generic_form_instance.html" %}
<input type="hidden" name="next" value="{{ next|escape }}" />
<div class="group navform wat-cf">
<button class="button" type="submit">
<img src="{{ STATIC_URL }}web_theme_media/images/icons/key.png" alt="Save" /> Login
</button>
</div>
</form>
</div>
</div>
</div>
{% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %}
{% if verbose_login %}
{% include "verbose_login.html" %}
{% endif %}
{% endblock %}
{% endif %}

View File

@@ -1,5 +1,7 @@
Version 0.12
------------
* Added new configuration option COMMON_ALLOW_ANONYMOUS_ACCESS to allow
non authenticated access.
* Statistics fixes
* Italian translation by SeeOpen.IT (www.seeopen.it, info@seeopen.it)
* Removed the 'db_index' argument from Text fields definition and

View File

@@ -188,7 +188,7 @@ Job processor
Default: ``None``
Specified which job processing library to use, option are: None and celery.
Specifies which job processing library to use, option are: None and celery.
Document indexing
@@ -230,12 +230,17 @@ OCR
.. data:: OCR_TESSERACT_PATH
Default: ``/bin/tesseract``
File path to the ``tesseract`` executable, used to perform OCR on document
page's images.
.. data:: OCR_TESSERACT_LANGUAGE
Default: ``eng``
Language code passed to the ``tesseract`` executable.
.. data:: OCR_REPLICATION_DELAY
@@ -256,7 +261,8 @@ OCR
Default: ``False``
Automatically queue newly created documents for OCR.
Automatically queue newly created documents or newly uploaded versions
of existing documents for OCR.
.. data:: OCR_QUEUE_PROCESSING_INTERVAL
@@ -277,7 +283,8 @@ OCR
Default: ``/usr/bin/unpaper``
File path to unpaper program.
File path to the ``unpaper`` executable, used to clean up images before
doing OCR.
Metadata
@@ -318,24 +325,39 @@ Common
.. data:: COMMON_AUTO_CREATE_ADMIN
Default: ``True``
Automatically creates an administrator superuser with the username
specified by COMMON_AUTO_ADMIN_USERNAME and with the default password
specified by COMMON_AUTO_ADMIN_PASSWORD
.. data:: COMMON_AUTO_ADMIN_USERNAME
Default: ``admin``
Username of the automatically created superuser
.. data:: COMMON_AUTO_ADMIN_PASSWORD
Default: ``admin``
Default password of the automatically created superuser
.. data:: COMMON_LOGIN_METHOD
Default: ``username``
Controls the mechanism used to authenticated user. Options are: ``username``, ``email``
.. data:: COMMON_ALLOW_ANONYMOUS_ACCESS
Default: ``False``
Allow non authenticated users, access to all views
Search
------

View File

@@ -149,12 +149,12 @@ INSTALLED_APPS = (
'sentry.client.celery',
'storage',
'folders',
'taggit',
'tags',
'document_comments',
'user_management',
'metadata',
'documents',
'taggit',
'tags',
'linking',
'mptt',
'document_indexing',
@@ -176,10 +176,8 @@ INSTALLED_APPS = (
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.i18n',
#'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.request',
# 'django.contrib.messages.context_processors.messages',
)
STATICFILES_FINDERS = (