From eb267cae1084df2c82eb6409e777846a4118c41b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:18:42 -0400 Subject: [PATCH 01/27] Add a Singleton Model class and an AnonymousUserSingleton model to support adding permissions and access to anonymous users --- apps/common/models.py | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/apps/common/models.py b/apps/common/models.py index 71a8362390..1e174119bb 100644 --- a/apps/common/models.py +++ b/apps/common/models.py @@ -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') From a020b011dcbf61cd1679761b78d4d4cf509bf2e5 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:20:39 -0400 Subject: [PATCH 02/27] Expose main app properties as project properties --- __init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/__init__.py b/__init__.py index e69de29bb2..a373a640b0 100644 --- a/__init__.py +++ b/__init__.py @@ -0,0 +1,2 @@ +from main import (__version__, __author__, __copyright__, __credits__, + __license__, __maintainer__, __email__, __status__) From 28000ccfec34585f526bbd0791420187d226bed0 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:21:22 -0400 Subject: [PATCH 03/27] Add proper permission checking to the ACL setup view links --- apps/acls/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/acls/__init__.py b/apps/acls/__init__.py index 5ca2e83361..eae1816727 100644 --- a/apps/acls/__init__.py +++ b/apps/acls/__init__.py @@ -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]) From d0acea071415a8fc8b82ab3cb22aaa51b6944f55 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:22:03 -0400 Subject: [PATCH 04/27] Add anonymous user support to the object encapsulator class --- apps/acls/classes.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/acls/classes.py b/apps/acls/classes.py index 1b6820c9e6..bcca9a6971 100644 --- a/apps/acls/classes.py +++ b/apps/acls/classes.py @@ -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: From b9f7939e3ee40c38e999e933b5b06a3c10793b0d Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:22:55 -0400 Subject: [PATCH 05/27] Add the anonymous user singleton to the list of avaible holder for an acl --- apps/acls/forms.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/acls/forms.py b/apps/acls/forms.py index 8adfaef90e..13777cf98e 100644 --- a/apps/acls/forms.py +++ b/apps/acls/forms.py @@ -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 From 595e901b64ac78970248168aa700b2bbcf34aff1 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:24:04 -0400 Subject: [PATCH 06/27] Add anonymous user support to the acl model manager methods --- apps/acls/managers.py | 7 ++++++- apps/acls/models.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/acls/managers.py b/apps/acls/managers.py index 0b22db3cbd..a2cb9ff17f 100644 --- a/apps/acls/managers.py +++ b/apps/acls/managers.py @@ -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: diff --git a/apps/acls/models.py b/apps/acls/models.py index b175601949..7aa847a88d 100644 --- a/apps/acls/models.py +++ b/apps/acls/models.py @@ -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 From 33513d34a582d0c53ca66ef2985f3376fb03c0f8 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:25:54 -0400 Subject: [PATCH 07/27] Remove remarked code --- apps/acls/views.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/acls/views.py b/apps/acls/views.py index 25445a9bbc..f0332fe33e 100644 --- a/apps/acls/views.py +++ b/apps/acls/views.py @@ -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)))}, From df5f50f5d47b4f80324a1e03c61181214a8de0e8 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:28:26 -0400 Subject: [PATCH 08/27] Cleanup auto admin user creation using receiver decorator --- apps/common/__init__.py | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/apps/common/__init__.py b/apps/common/__init__.py index 4212752ca8..b0557cce5c 100644 --- a/apps/common/__init__.py +++ b/apps/common/__init__.py @@ -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,37 @@ 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. +#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 admin super user automatically. - def create_testuser(app, created_models, verbosity, **kwargs): +@receiver(post_syncdb, dispatch_uid='create_superuser', sender=auth_models) +#def create_superuser(app, created_models, verbosity, **kwargs): +def create_superuser(sender, **kwargs): + 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) +#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') if (validate_path(common_settings.TEMPORARY_DIRECTORY) == False) or (not common_settings.TEMPORARY_DIRECTORY): setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp()) From fa94288317ca7911ffdd32180ab8cf38bae44c1f Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:29:03 -0400 Subject: [PATCH 09/27] Only add the sentry and admin add and icons if they corresponding apps have been installed --- apps/main/__init__.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/main/__init__.py b/apps/main/__init__.py index b3c1b6a1e8..842c5d11ab 100644 --- a/apps/main/__init__.py +++ b/apps/main/__init__.py @@ -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) From 51b63e86de651a7bb50f808ce5ee2679cf37665b Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:29:42 -0400 Subject: [PATCH 10/27] Add corresponding permission check to the source app view links --- apps/sources/__init__.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/sources/__init__.py b/apps/sources/__init__.py index 9fc8b93965..62027a4734 100644 --- a/apps/sources/__init__.py +++ b/apps/sources/__init__.py @@ -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]} From 367d197cc0db03f060d56351b659007a6aa08e92 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:30:35 -0400 Subject: [PATCH 11/27] Add 'get_for_user' method to the RecentDocument model --- apps/documents/managers.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/documents/managers.py b/apps/documents/managers.py index 8c07b5ec54..189535a67d 100644 --- a/apps/documents/managers.py +++ b/apps/documents/managers.py @@ -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): From 4931d9bf4968e8e6cec49c29931a9598da21a1ce Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:30:58 -0400 Subject: [PATCH 12/27] Update recent document list view to user the 'get_for_user' RecentDocument manager method --- apps/documents/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/documents/views.py b/apps/documents/views.py index a5deae4f53..2ccecd62bf 100644 --- a/apps/documents/views.py +++ b/apps/documents/views.py @@ -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 From c7ee18af8571a399b5327763058b43348e16be45 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:33:09 -0400 Subject: [PATCH 13/27] Add anonymous user support to the 'get_object_name' function --- apps/common/utils.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/common/utils.py b/apps/common/utils.py index da13756918..dd916980d6 100644 --- a/apps/common/utils.py +++ b/apps/common/utils.py @@ -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) From 85875be8592f68e3e682e8ae4c4fa6fe43e285d6 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:33:31 -0400 Subject: [PATCH 14/27] Add further auto admin creation cleanups --- apps/common/__init__.py | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/apps/common/__init__.py b/apps/common/__init__.py index b0557cce5c..9dcd406a4f 100644 --- a/apps/common/__init__.py +++ b/apps/common/__init__.py @@ -33,19 +33,19 @@ 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 admin super user automatically. - @receiver(post_syncdb, dispatch_uid='create_superuser', sender=auth_models) -#def create_superuser(app, created_models, verbosity, **kwargs): def create_superuser(sender, **kwargs): + """ + 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 admin super user automatically. + """ + if common_settings.AUTO_CREATE_ADMIN: USERNAME = common_settings.AUTO_ADMIN_USERNAME PASSWORD = common_settings.AUTO_ADMIN_PASSWORD @@ -58,12 +58,6 @@ def create_superuser(sender, **kwargs): assert auth_models.User.objects.create_superuser(USERNAME, 'x@x.com', PASSWORD) else: print 'Super admin 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') if (validate_path(common_settings.TEMPORARY_DIRECTORY) == False) or (not common_settings.TEMPORARY_DIRECTORY): setattr(common_settings, 'TEMPORARY_DIRECTORY', tempfile.mkdtemp()) From cbc94e484f02c1844d7935d76de38c848338c1a7 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:36:07 -0400 Subject: [PATCH 15/27] Add anonymous user support to the Permission manager models --- apps/permissions/managers.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/permissions/managers.py b/apps/permissions/managers.py index a6d5cc4722..38a94ceee4 100644 --- a/apps/permissions/managers.py +++ b/apps/permissions/managers.py @@ -8,11 +8,16 @@ 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)] From 0c02ac7d40bdedd87c5082345388875906a03769 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sat, 7 Jan 2012 23:36:41 -0400 Subject: [PATCH 16/27] Add anonymous user support to the dynamic search app's Savedsearch model manager method --- apps/dynamic_search/managers.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/dynamic_search/managers.py b/apps/dynamic_search/managers.py index 5df299ac2c..e825bc7350 100644 --- a/apps/dynamic_search/managers.py +++ b/apps/dynamic_search/managers.py @@ -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 From be1658505c4d8c829f2338f278739a94926dee89 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:40:02 -0400 Subject: [PATCH 17/27] Use a context variable (web_theme_view_type) to determine the web theme view mode instead of using the user login status --- apps/web_theme/templates/web_theme_base.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/web_theme/templates/web_theme_base.html b/apps/web_theme/templates/web_theme_base.html index 56aa5294cb..d60b8368df 100644 --- a/apps/web_theme/templates/web_theme_base.html +++ b/apps/web_theme/templates/web_theme_base.html @@ -69,7 +69,7 @@
- {% if user.is_anonymous %} + {% if web_theme_view_type == 'plain' %}
{% block content_plain %}{% endblock %}
From 9d73c10b7b6ac83d9f779e6b9fc7b9cc7323a2ee Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:41:07 -0400 Subject: [PATCH 18/27] Invert authentication test logic from is_anonymous to not is_authenticated From: http://gdub.wordpress.com/2006/09/23/is_authenticated-vs-is_anonymous/ --- apps/web_theme/templates/web_theme_login.html | 83 ++++++++++--------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/apps/web_theme/templates/web_theme_login.html b/apps/web_theme/templates/web_theme_login.html index ca98f0c7e9..302e371226 100644 --- a/apps/web_theme/templates/web_theme_login.html +++ b/apps/web_theme/templates/web_theme_login.html @@ -3,51 +3,52 @@ {% load theme_tags %} {% block web_theme_head %} - {% if not user.is_anonymous %} + {% if user.is_authenticated %} {% get_login_redirect_url %} {% endif %} {% endblock %} {% block html_title %}{% trans "Login" %}{% endblock %} -{% if not user.is_anonymous %} - {% block web_theme_content %} - {% get_login_redirect_url %} -
-

{% trans "You are already logged in" %}

-
-

- {% trans "Redirecting you to the website entry point in 5 seconds." %} -

-

- {% blocktrans %}Or click here if redirection doesn't work.{% endblocktrans %} -

-
-
- {% endblock %} -{% else %} - {% block content_plain %} -
-

{% block project_name %}{% endblock %}

-
-

{% trans "Login" %}

- - {% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %} - {% if verbose_login %} - {% include "verbose_login.html" %} - {% endif %} - {% endblock %} -{% endif %} + {% endblock %} + {% else %} + {% block content_plain %} +
+

{% block project_name %}{% endblock %}

+
+

{% trans "Login" %}

+ +
+ {% get_web_theme_setting "VERBOSE_LOGIN" as verbose_login %} + {% if verbose_login %} + {% include "verbose_login.html" %} + {% endif %} + {% endblock %} + {% endif %} From 467be05baaec7c4c731e0d7ac3b91f578b7928ef Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:42:01 -0400 Subject: [PATCH 19/27] Select the proper web theme display mode based on the user authentication status --- apps/common/views.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/common/views.py b/apps/common/views.py index c88a204362..c7969ad5c3 100644 --- a/apps/common/views.py +++ b/apps/common/views.py @@ -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): From c2fcbfe2991b777987a5e546812f3fbbb9f49d6a Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:54:15 -0400 Subject: [PATCH 20/27] Add COMMON_ALLOW_ANONYMOUS_ACCESS configuration option to allow access to non authenticated users --- apps/common/conf/settings.py | 9 ++++++ .../middleware/login_required_middleware.py | 25 +++++++++------ docs/changelog.rst | 2 ++ docs/settings.rst | 32 ++++++++++++++++--- 4 files changed, 53 insertions(+), 15 deletions(-) diff --git a/apps/common/conf/settings.py b/apps/common/conf/settings.py index 14640aeb2e..3372111a51 100644 --- a/apps/common/conf/settings.py +++ b/apps/common/conf/settings.py @@ -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'Allows non authenticated users access to all views'), +) diff --git a/apps/common/middleware/login_required_middleware.py b/apps/common/middleware/login_required_middleware.py index 91af7dc92f..94331d32aa 100644 --- a/apps/common/middleware/login_required_middleware.py +++ b/apps/common/middleware/login_required_middleware.py @@ -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) diff --git a/docs/changelog.rst b/docs/changelog.rst index d06b77d2d2..89feffda1a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -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 diff --git a/docs/settings.rst b/docs/settings.rst index 323bf84405..8d9b0237be 100644 --- a/docs/settings.rst +++ b/docs/settings.rst @@ -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 ------ From ad5dfdd148981c4b6bba872269365ca82c8a1804 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:55:13 -0400 Subject: [PATCH 21/27] Removed remarked lines --- settings.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/settings.py b/settings.py index 9a64a7ce74..1944232ed5 100644 --- a/settings.py +++ b/settings.py @@ -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 = ( From f2a263adb710253a650ea55a92c721f7c215ea94 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:55:54 -0400 Subject: [PATCH 22/27] Move tag model column registration to the tags app --- apps/documents/__init__.py | 4 ---- apps/tags/__init__.py | 11 +++++++++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/apps/documents/__init__.py b/apps/documents/__init__.py index aa8ec09269..45fd4c5ad7 100644 --- a/apps/documents/__init__.py +++ b/apps/documents/__init__.py @@ -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)) }, diff --git a/apps/tags/__init__.py b/apps/tags/__init__.py index 357b4b878c..8cfeacf58b 100644 --- a/apps/tags/__init__.py +++ b/apps/tags/__init__.py @@ -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') From 7fd83ddf0b286ecc0b8881701b3695188d8808dd Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:57:02 -0400 Subject: [PATCH 23/27] Fix import format --- apps/permissions/templatetags/permission_tags.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/permissions/templatetags/permission_tags.py b/apps/permissions/templatetags/permission_tags.py index 18e161bdd7..0d0974145b 100644 --- a/apps/permissions/templatetags/permission_tags.py +++ b/apps/permissions/templatetags/permission_tags.py @@ -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 From c3175c7ea40cdbc7778d2b7b2a67884a152fc53e Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:57:54 -0400 Subject: [PATCH 24/27] Add anonymous user support to the permission app --- apps/permissions/managers.py | 1 - apps/permissions/models.py | 15 +++++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/permissions/managers.py b/apps/permissions/managers.py index 38a94ceee4..2284f55e01 100644 --- a/apps/permissions/managers.py +++ b/apps/permissions/managers.py @@ -17,7 +17,6 @@ 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)] diff --git a/apps/permissions/models.py b/apps/permissions/models.py index 744703f1c3..2ec16fe68f 100644 --- a/apps/permissions/models.py +++ b/apps/permissions/models.py @@ -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), From 45031022b6dcd637e4c5d46b966e39b1043d333d Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:58:22 -0400 Subject: [PATCH 25/27] Update COMMON_ALLOW_ANONYMOUS_ACCESS description wording --- apps/common/conf/settings.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/conf/settings.py b/apps/common/conf/settings.py index 3372111a51..e1ec67ada3 100644 --- a/apps/common/conf/settings.py +++ b/apps/common/conf/settings.py @@ -71,5 +71,5 @@ register_setting( name=u'ALLOW_ANONYMOUS_ACCESS', global_name=u'COMMON_ALLOW_ANONYMOUS_ACCESS', default=False, - description=_(u'Allows non authenticated users access to all views'), + description=_(u'Allow non authenticated users, access to all views'), ) From 3ef44b3d324c556f55d8511a6bebb53e5b3cf79c Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:58:42 -0400 Subject: [PATCH 26/27] Update logout action to not redirect on logout --- apps/main/templates/base.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/main/templates/base.html b/apps/main/templates/base.html index c1fcedd0cb..ab7c60ca26 100644 --- a/apps/main/templates/base.html +++ b/apps/main/templates/base.html @@ -181,7 +181,7 @@ {% block web_theme_user_navigation %}
  • {% trans "User" %}: - {% if user.is_anonymous %} + {% if not user.is_authenticated %} {% trans "Anonymous" %} {% else %} {{ user.get_full_name|default:user }} @@ -202,7 +202,7 @@
  • {% endif %} {% get_setting "LOGIN_URL" as login_url %} -
  • {% if user.is_anonymous %}{% trans "Login" %}{% else %}{% trans "Logout" %}{% endif %}
  • +
  • {% if not user.is_authenticated %}{% trans "Login" %}{% else %}{% trans "Logout" %}{% endif %}
  • {% endblock %} {% block web_theme_main_navigation %} From 51a6abaf117081ed52aad19203d1c1159bc241b6 Mon Sep 17 00:00:00 2001 From: Roberto Rosario Date: Sun, 8 Jan 2012 04:59:16 -0400 Subject: [PATCH 27/27] Add context variable setting helper template tag --- apps/common/templatetags/set_var.py | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 apps/common/templatetags/set_var.py diff --git a/apps/common/templatetags/set_var.py b/apps/common/templatetags/set_var.py new file mode 100644 index 0000000000..c818a7188c --- /dev/null +++ b/apps/common/templatetags/set_var.py @@ -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 = %} + """ + parts = token.split_contents() + if len(parts) < 4: + raise template.TemplateSyntaxError("'set' tag must be of the form: {% set = %}") + return SetVarNode(parts[1], parts[3]) + +register.tag('set', set_var)