Merge branch 'feature/anonymous_support' into development
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
from main import (__version__, __author__, __copyright__, __credits__,
|
||||
__license__, __maintainer__, __email__, __status__)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)))},
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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'),
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
30
apps/common/templatetags/set_var.py
Normal file
30
apps/common/templatetags/set_var.py
Normal 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)
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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))
|
||||
},
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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)]
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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]}
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 %}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
------
|
||||
|
||||
@@ -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 = (
|
||||
|
||||
Reference in New Issue
Block a user