Final changes to support permissions and roles
This commit is contained in:
@@ -20,6 +20,7 @@ Features
|
||||
* Previews for a great deal of image formats, including PDF
|
||||
* Document OCR and searching
|
||||
* Group documents by metadata automatically
|
||||
* Permissions and roles support
|
||||
|
||||
Requirements
|
||||
---
|
||||
|
||||
@@ -2,9 +2,6 @@ import copy
|
||||
|
||||
from django.db.utils import DatabaseError
|
||||
|
||||
from permissions.utils import has_permission
|
||||
from permissions.models import Permission
|
||||
|
||||
|
||||
object_navigation = {}
|
||||
menu_links = []
|
||||
@@ -44,25 +41,3 @@ def register_model_list_columns(model, columns):
|
||||
model_list_columns[model].extend(columns)
|
||||
else:
|
||||
model_list_columns[model] = copy.copy(columns)
|
||||
|
||||
|
||||
def register_permissions(app, permissions):
|
||||
if permissions:
|
||||
for permission in permissions:
|
||||
full_permission_name = "%s_%s" % (app, permission['name'])
|
||||
try:
|
||||
#if not Permission.objects.filter(codename=full_permission_name):
|
||||
# Permission(name=unicode(permission['label']), codename=full_permission_name).save()
|
||||
permission_obj, created = Permission.objects.get_or_create(codename=full_permission_name)
|
||||
permission_obj.name=unicode(permission['label'])
|
||||
permission_obj.save()
|
||||
except DatabaseError:
|
||||
#Special case for ./manage.py syncdb
|
||||
pass
|
||||
|
||||
|
||||
def check_permissions(object, user, permission_list):
|
||||
temp_role = []
|
||||
for permission in permission_list:
|
||||
if has_permission(object, user, permission):
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,17 @@
|
||||
{% load i18n %}
|
||||
{% load permission_tags %}
|
||||
|
||||
{% for link in object_navigation_links %}
|
||||
{% if link.permissions %}
|
||||
{% check_permissions request.user link.permissions.namespace link.permissions.permissions %}
|
||||
{% if permission %}
|
||||
{% if as_li %}<li>{% endif %}
|
||||
<a class="{{ link.class }}" href="{{ link.url }}">{% if link.famfam %}<span class="famfam active famfam-{{ link.famfam|default:'link' }}"></span>{% endif %}{{ link.text|capfirst }}{% if link.error %} - {{ link.error }}{% endif %}{% if link.active %}<span class="famfam active famfam-resultset_previous"></span>{% endif %}</a>{% if horizontal %}{% if not forloop.last %} | {% endif %}{% endif %}
|
||||
{% if as_li %}</li>{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if as_li %}<li>{% endif %}
|
||||
<a class="{{ link.class }}" href="{{ link.url }}">{% if link.famfam %}<span class="famfam active famfam-{{ link.famfam|default:'link' }}"></span>{% endif %}{{ link.text|capfirst }}{% if link.error %} - {{ link.error }}{% endif %}{% if link.active %}<span class="famfam active famfam-resultset_previous"></span>{% endif %}</a>{% if horizontal %}{% if not forloop.last %} | {% endif %}{% endif %}
|
||||
{% if as_li %}</li>{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,25 +4,42 @@ from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.urlresolvers import reverse
|
||||
|
||||
from common.api import register_links, register_menu, \
|
||||
register_model_list_columns, register_permissions
|
||||
register_model_list_columns
|
||||
from common.utils import pretty_size
|
||||
|
||||
from permissions.api import register_permissions
|
||||
|
||||
from models import Document
|
||||
from staging import StagingFile
|
||||
|
||||
from documents.conf import settings as documents_settings
|
||||
|
||||
PERMISSION_DOCUMENT_CREATE = 'document_create'
|
||||
PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit'
|
||||
PERMISSION_DOCUMENT_METADATA_EDIT = 'document_metadata_edit'
|
||||
PERMISSION_DOCUMENT_VIEW = 'document_view'
|
||||
PERMISSION_DOCUMENT_DELETE = 'document_delete'
|
||||
PERMISSION_DOCUMENT_DOWNLOAD = 'document_download'
|
||||
|
||||
document_list = {'text':_(u'documents list'), 'view':'document_list', 'famfam':'page'}
|
||||
document_create = {'text':_('upload a document'), 'view':'document_create', 'famfam':'page_add'}
|
||||
document_create_multiple = {'text':_('upload multiple documents'), 'view':'document_create_multiple', 'famfam':'page_add'}
|
||||
document_create_sibling = {'text':_('upload using same metadata'), 'view':'document_create_sibling', 'args':'object.id', 'famfam':'page_copy'}
|
||||
document_view = {'text':_('details'), 'view':'document_view', 'args':'object.id', 'famfam':'page'}
|
||||
document_delete = {'text':_('delete'), 'view':'document_delete', 'args':'object.id', 'famfam':'page_delete'}
|
||||
document_edit = {'text':_('edit'), 'view':'document_edit', 'args':'object.id', 'famfam':'page_edit'}
|
||||
document_edit_metadata = {'text':_('edit metadata'), 'view':'document_edit_metadata', 'args':'object.id', 'famfam':'page_edit'}
|
||||
document_preview = {'text':_('preview'), 'class':'fancybox', 'view':'document_preview', 'args':'object.id', 'famfam':'magnifier'}
|
||||
document_download = {'text':_('download'), 'view':'document_download', 'args':'object.id', 'famfam':'page_save'}
|
||||
register_permissions('documents', [
|
||||
{'name':PERMISSION_DOCUMENT_CREATE, 'label':_(u'Create document')},
|
||||
{'name':PERMISSION_DOCUMENT_PROPERTIES_EDIT, 'label':_(u'Edit document properties')},
|
||||
{'name':PERMISSION_DOCUMENT_METADATA_EDIT, 'label':_(u'Edit document metadata')},
|
||||
{'name':PERMISSION_DOCUMENT_VIEW, 'label':_(u'View document')},
|
||||
{'name':PERMISSION_DOCUMENT_DELETE, 'label':_(u'Delete document')},
|
||||
{'name':PERMISSION_DOCUMENT_DOWNLOAD, 'label':_(u'Download document')},
|
||||
])
|
||||
|
||||
document_list = {'text':_(u'documents list'), 'view':'document_list', 'famfam':'page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}}
|
||||
document_create = {'text':_('upload a document'), 'view':'document_create', 'famfam':'page_add', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}}
|
||||
document_create_multiple = {'text':_('upload multiple documents'), 'view':'document_create_multiple', 'famfam':'page_add', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}}
|
||||
document_create_sibling = {'text':_('upload using same metadata'), 'view':'document_create_sibling', 'args':'object.id', 'famfam':'page_copy', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_CREATE]}}
|
||||
document_view = {'text':_('details'), 'view':'document_view', 'args':'object.id', 'famfam':'page', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}}
|
||||
document_delete = {'text':_('delete'), 'view':'document_delete', 'args':'object.id', 'famfam':'page_delete', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_DELETE]}}
|
||||
document_edit = {'text':_('edit'), 'view':'document_edit', 'args':'object.id', 'famfam':'page_edit', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_PROPERTIES_EDIT]}}
|
||||
document_edit_metadata = {'text':_('edit metadata'), 'view':'document_edit_metadata', 'args':'object.id', 'famfam':'page_edit', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_METADATA_EDIT]}}
|
||||
document_preview = {'text':_('preview'), 'class':'fancybox', 'view':'document_preview', 'args':'object.id', 'famfam':'magnifier', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_VIEW]}}
|
||||
document_download = {'text':_('download'), 'view':'document_download', 'args':'object.id', 'famfam':'page_save', 'permissions':{'namespace':'documents', 'permissions':[PERMISSION_DOCUMENT_DOWNLOAD]}}
|
||||
|
||||
staging_file_preview = {'text':_('preview'), 'class':'fancybox', 'view':'staging_file_preview', 'args':'object.id', 'famfam':'drive_magnify'}
|
||||
staging_file_delete = {'text':_('delete'), 'view':'staging_file_delete', 'args':'object.id', 'famfam':'drive_delete'}
|
||||
@@ -50,21 +67,3 @@ register_menu([
|
||||
],'famfam':'page','position':4}])
|
||||
|
||||
TEMPORARY_DIRECTORY = documents_settings.TEMPORARY_DIRECTORY if documents_settings.TEMPORARY_DIRECTORY else tempfile.mkdtemp()
|
||||
|
||||
PERMISSION_DOCUMENT_CREATE = 'document_create'
|
||||
PERMISSION_DOCUMENT_PROPERTIES_EDIT = 'document_properties_edit'
|
||||
PERMISSION_DOCUMENT_METADATA_EDIT = 'document_metadata_edit'
|
||||
PERMISSION_DOCUMENT_VIEW = 'document_view'
|
||||
PERMISSION_DOCUMENT_DELETE = 'document_delete'
|
||||
PERMISSION_DOCUMENT_OCR = 'document_ocr'
|
||||
PERMISSION_DOCUMENT_DOWNLOAD = 'document_download'
|
||||
|
||||
register_permissions('documents', [
|
||||
{'name':PERMISSION_DOCUMENT_CREATE, 'label':_(u'Create document')},
|
||||
{'name':PERMISSION_DOCUMENT_PROPERTIES_EDIT, 'label':_(u'Edit document properties')},
|
||||
{'name':PERMISSION_DOCUMENT_METADATA_EDIT, 'label':_(u'Edit document metadata')},
|
||||
{'name':PERMISSION_DOCUMENT_VIEW, 'label':_(u'View document')},
|
||||
{'name':PERMISSION_DOCUMENT_DELETE, 'label':_(u'Delete document')},
|
||||
{'name':PERMISSION_DOCUMENT_OCR, 'label':_(u'Submit document for OCR')},
|
||||
{'name':PERMISSION_DOCUMENT_DOWNLOAD, 'label':_(u'Download document')},
|
||||
])
|
||||
|
||||
@@ -11,7 +11,7 @@ from django.conf import settings
|
||||
from django.utils.http import urlencode
|
||||
from django.template.defaultfilters import slugify
|
||||
|
||||
|
||||
from permissions.api import check_permissions, Unauthorized
|
||||
from filetransfers.api import serve_file
|
||||
from converter.api import convert, in_image_cache, QUALITY_DEFAULT
|
||||
from common.utils import pretty_size
|
||||
@@ -38,13 +38,17 @@ from documents.conf.settings import GROUP_SHOW_EMPTY
|
||||
from documents import PERMISSION_DOCUMENT_CREATE, \
|
||||
PERMISSION_DOCUMENT_CREATE, PERMISSION_DOCUMENT_PROPERTIES_EDIT, \
|
||||
PERMISSION_DOCUMENT_METADATA_EDIT, PERMISSION_DOCUMENT_VIEW, \
|
||||
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_OCR, \
|
||||
PERMISSION_DOCUMENT_DOWNLOAD
|
||||
|
||||
PERMISSION_DOCUMENT_DELETE, PERMISSION_DOCUMENT_DOWNLOAD
|
||||
|
||||
from utils import save_metadata, save_metadata_list, decode_metadata_from_url
|
||||
|
||||
def document_list(request):
|
||||
permissions = [PERMISSION_DOCUMENT_VIEW]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
return object_list(
|
||||
request,
|
||||
queryset=Document.objects.all(),
|
||||
@@ -56,8 +60,10 @@ def document_list(request):
|
||||
|
||||
def document_create(request, multiple=True):
|
||||
permissions = [PERMISSION_DOCUMENT_CREATE]
|
||||
if not check_permissions(main_object, request.user, permissions):
|
||||
raise Http404
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
if DocumentType.objects.all().count() == 1:
|
||||
wizard = DocumentCreateWizard(
|
||||
@@ -72,6 +78,12 @@ def document_create(request, multiple=True):
|
||||
return wizard(request)
|
||||
|
||||
def document_create_sibling(request, document_id, multiple=True):
|
||||
permissions = [PERMISSION_DOCUMENT_CREATE]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
urldata = []
|
||||
for id, metadata in enumerate(document.documentmetadata_set.all()):
|
||||
@@ -89,6 +101,12 @@ def document_create_sibling(request, document_id, multiple=True):
|
||||
|
||||
|
||||
def upload_document_with_type(request, document_type_id, multiple=True):
|
||||
permissions = [PERMISSION_DOCUMENT_CREATE]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document_type = get_object_or_404(DocumentType, pk=document_type_id)
|
||||
local_form = DocumentForm(prefix='local', initial={'document_type':document_type})
|
||||
if USE_STAGING_DIRECTORY:
|
||||
@@ -206,6 +224,12 @@ def upload_document_with_type(request, document_type_id, multiple=True):
|
||||
context_instance=RequestContext(request))
|
||||
|
||||
def document_view(request, document_id):
|
||||
permissions = [PERMISSION_DOCUMENT_VIEW]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
form = DocumentForm_view(instance=document, extra_fields=[
|
||||
{'label':_(u'Filename'), 'field':'file_filename'},
|
||||
@@ -285,6 +309,12 @@ def document_view(request, document_id):
|
||||
|
||||
|
||||
def document_delete(request, document_id):
|
||||
permissions = [PERMISSION_DOCUMENT_DELETE]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
|
||||
return delete_object(request, model=Document, object_id=document_id,
|
||||
@@ -298,6 +328,12 @@ def document_delete(request, document_id):
|
||||
|
||||
|
||||
def document_edit(request, document_id):
|
||||
permissions = [PERMISSION_DOCUMENT_PROPERTIES_EDIT]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
if request.method == 'POST':
|
||||
form = DocumentForm_edit(request.POST, initial={'document_type':document.document_type})
|
||||
@@ -338,6 +374,12 @@ def document_edit(request, document_id):
|
||||
|
||||
|
||||
def document_edit_metadata(request, document_id):
|
||||
permissions = [PERMISSION_DOCUMENT_METADATA_EDIT]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
|
||||
initial=[]
|
||||
@@ -386,6 +428,12 @@ def document_edit_metadata(request, document_id):
|
||||
|
||||
|
||||
def get_document_image(request, document_id, size=PREVIEW_SIZE, quality=QUALITY_DEFAULT):
|
||||
permissions = [PERMISSION_DOCUMENT_VIEW]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
|
||||
try:
|
||||
@@ -407,6 +455,12 @@ def get_document_image(request, document_id, size=PREVIEW_SIZE, quality=QUALITY_
|
||||
|
||||
|
||||
def document_download(request, document_id):
|
||||
permissions = [PERMISSION_DOCUMENT_DOWNLOAD]
|
||||
try:
|
||||
check_permissions(request.user, 'documents', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
try:
|
||||
#Test permissions and trigger exception
|
||||
@@ -417,6 +471,7 @@ def document_download(request, document_id):
|
||||
return HttpResponseRedirect(request.META['HTTP_REFERER'])
|
||||
|
||||
|
||||
#TODO: Need permission
|
||||
def staging_file_preview(request, staging_file_id):
|
||||
try:
|
||||
filepath = StagingFile.get(staging_file_id).filepath
|
||||
@@ -426,6 +481,7 @@ def staging_file_preview(request, staging_file_id):
|
||||
return serve_file(request, File(file=open('%simages/1297211435_error.png' % settings.MEDIA_ROOT, 'r')))
|
||||
|
||||
|
||||
#TODO: Need permission
|
||||
def staging_file_delete(request, staging_file_id):
|
||||
staging_file = StagingFile.get(staging_file_id)
|
||||
next = request.POST.get('next', request.GET.get('next', request.META.get('HTTP_REFERER', None)))
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.api import register_links, register_menu
|
||||
from permissions.api import register_permissions
|
||||
|
||||
from documents.models import Document
|
||||
|
||||
OCR_DOCUMENT_OCR = 'document_ocr'
|
||||
|
||||
submit_document = {'text':_('submit to OCR queue'), 'view':'submit_document', 'args':'object.id', 'famfam':'page_lightning'}
|
||||
register_permissions('ocr', [
|
||||
{'name':OCR_DOCUMENT_OCR, 'label':_(u'Submit document for OCR')},
|
||||
])
|
||||
|
||||
submit_document = {'text':_('submit to OCR queue'), 'view':'submit_document', 'args':'object.id', 'famfam':'page_lightning', 'permissions':{'namespace':'ocr', 'permissions':[OCR_DOCUMENT_OCR]}}
|
||||
|
||||
register_links(Document, [submit_document], menu_name='sidebar')
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.http import HttpResponse, HttpResponseRedirect, Http404
|
||||
from django.shortcuts import render_to_response, get_object_or_404, redirect
|
||||
from django.template import RequestContext
|
||||
from django.contrib import messages
|
||||
@@ -8,13 +8,19 @@ from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
|
||||
from permissions.api import check_permissions, Unauthorized
|
||||
from documents.models import Document
|
||||
|
||||
|
||||
from ocr import OCR_DOCUMENT_OCR
|
||||
from api import ocr_document
|
||||
|
||||
def submit_document(request, document_id):
|
||||
permissions = [OCR_DOCUMENT_OCR]
|
||||
try:
|
||||
check_permissions(request.user, 'ocr', permissions)
|
||||
except Unauthorized, e:
|
||||
raise Http404(e)
|
||||
|
||||
document = get_object_or_404(Document, pk=document_id)
|
||||
|
||||
try:
|
||||
|
||||
21
apps/permissions/__init__.py
Normal file
21
apps/permissions/__init__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from django.contrib.auth.models import User
|
||||
from django.db.models.signals import post_save
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from permissions.conf.settings import DEFAULT_ROLES
|
||||
|
||||
from models import Role
|
||||
|
||||
|
||||
def user_post_save(sender, instance, **kwargs):
|
||||
for default_role in DEFAULT_ROLES:
|
||||
if isinstance(default_role, Role):
|
||||
default_role.add_member(instance)
|
||||
else:
|
||||
try:
|
||||
role = Role.objects.get(name=default_role)
|
||||
role.add_member(instance)
|
||||
except ObjectDoesNotExist:
|
||||
pass
|
||||
|
||||
post_save.connect(user_post_save, sender=User)
|
||||
33
apps/permissions/admin.py
Normal file
33
apps/permissions/admin.py
Normal file
@@ -0,0 +1,33 @@
|
||||
from django.contrib import admin
|
||||
|
||||
from models import Permission, PermissionHolder, Role, RoleMember
|
||||
from django.contrib.contenttypes import generic
|
||||
|
||||
|
||||
class PermissionHolderInline(admin.StackedInline):
|
||||
model = PermissionHolder
|
||||
extra = 1
|
||||
classes = ('collapse-open',)
|
||||
allow_add = True
|
||||
|
||||
|
||||
class PermissionAdmin(admin.ModelAdmin):
|
||||
inlines = [PermissionHolderInline]
|
||||
list_display = ('namespace', 'name', 'label')
|
||||
list_display_links = list_display
|
||||
|
||||
|
||||
class RoleMemberInline(admin.StackedInline):
|
||||
model = RoleMember
|
||||
extra = 1
|
||||
classes = ('collapse-open',)
|
||||
allow_add = True
|
||||
|
||||
|
||||
class RoleAdmin(admin.ModelAdmin):
|
||||
inlines = [RoleMemberInline]
|
||||
|
||||
|
||||
admin.site.register(Permission, PermissionAdmin)
|
||||
admin.site.register(Role, RoleAdmin)
|
||||
|
||||
70
apps/permissions/api.py
Normal file
70
apps/permissions/api.py
Normal file
@@ -0,0 +1,70 @@
|
||||
from django.http import Http404
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.models import Group
|
||||
from django.db.utils import DatabaseError
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.translation import ugettext
|
||||
|
||||
from models import Permission, Role
|
||||
|
||||
class Unauthorized(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def register_permissions(namespace, permissions):
|
||||
if permissions:
|
||||
for permission in permissions:
|
||||
try:
|
||||
permission_obj, created = Permission.objects.get_or_create(
|
||||
namespace=namespace, name=permission['name'])
|
||||
permission_obj.label=unicode(permission['label'])
|
||||
permission_obj.save()
|
||||
except DatabaseError:
|
||||
#Special case for ./manage.py syncdb
|
||||
pass
|
||||
|
||||
#TODO: Handle anonymous users
|
||||
def check_permissions(requester, namespace, permission_list):
|
||||
if isinstance(requester, User):
|
||||
if requester.is_superuser:
|
||||
return True
|
||||
|
||||
for permission_item in permission_list:
|
||||
permission = get_object_or_404(Permission,
|
||||
namespace=namespace, name=permission_item)
|
||||
if check_permission(requester, permission):
|
||||
return True
|
||||
|
||||
raise Unauthorized(ugettext(u'Insufficient permissions.'))
|
||||
|
||||
|
||||
def check_permission(requester, permission):
|
||||
for permission_holder in permission.permissionholder_set.all():
|
||||
if check_requester(requester, permission_holder):
|
||||
return True
|
||||
|
||||
|
||||
def check_requester(requester, permission_holder):
|
||||
ct = ContentType.objects.get_for_model(requester)
|
||||
if permission_holder.holder_type == ct and permission_holder.holder_id == requester.id:
|
||||
return True
|
||||
|
||||
if isinstance(permission_holder.holder_object, Role):
|
||||
requester_list = [role_member.member_object for role_member in permission_holder.holder_object.rolemember_set.all()]
|
||||
if check_elements(requester, requester_list):
|
||||
return True
|
||||
|
||||
#Untested
|
||||
if isinstance(permission_holder.holder_object, Group):
|
||||
if check_elements(requester, permission_holder.holder_object.user_set.all()):
|
||||
return True
|
||||
|
||||
|
||||
#TODO: a role may contain groups, make recursive
|
||||
def check_elements(requester, requester_list):
|
||||
ct = ContentType.objects.get_for_model(requester)
|
||||
for requester_object in requester_list:
|
||||
if requester == requester_object:
|
||||
return True
|
||||
0
apps/permissions/conf/__init__.py
Normal file
0
apps/permissions/conf/__init__.py
Normal file
3
apps/permissions/conf/settings.py
Normal file
3
apps/permissions/conf/settings.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from django.conf import settings
|
||||
|
||||
DEFAULT_ROLES = getattr(settings, 'ROLES_DEFAULT_ROLES', [])
|
||||
67
apps/permissions/locale/es/LC_MESSAGES/django.po
Normal file
67
apps/permissions/locale/es/LC_MESSAGES/django.po
Normal file
@@ -0,0 +1,67 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2011-02-13 04:12-0400\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: api.py:40
|
||||
msgid "Insufficient permissions."
|
||||
msgstr ""
|
||||
|
||||
#: models.py:8
|
||||
msgid "namespace"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:9
|
||||
msgid "name"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:10 models.py:40
|
||||
msgid "label"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:14 models.py:23
|
||||
msgid "permission"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:15
|
||||
msgid "permissions"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:31
|
||||
msgid "permission holder"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:32
|
||||
msgid "permission holders"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:44 models.py:58
|
||||
msgid "role"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:45
|
||||
msgid "roles"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:67
|
||||
msgid "role member"
|
||||
msgstr ""
|
||||
|
||||
#: models.py:68
|
||||
msgid "role members"
|
||||
msgstr ""
|
||||
71
apps/permissions/models.py
Normal file
71
apps/permissions/models.py
Normal file
@@ -0,0 +1,71 @@
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.contenttypes import generic
|
||||
|
||||
|
||||
class Permission(models.Model):
|
||||
namespace = models.CharField(max_length=64, verbose_name=_(u'namespace'))
|
||||
name = models.CharField(max_length=64, verbose_name=_(u'name'))
|
||||
label = models.CharField(max_length=64, verbose_name=_(u'label'))
|
||||
|
||||
class Meta:
|
||||
unique_together = ('namespace', 'name')
|
||||
verbose_name = _(u'permission')
|
||||
verbose_name_plural = _(u'permissions')
|
||||
|
||||
|
||||
def __unicode__(self):
|
||||
return self.label
|
||||
|
||||
|
||||
class PermissionHolder(models.Model):
|
||||
permission = models.ForeignKey(Permission, verbose_name=_(u'permission'))
|
||||
holder_type = models.ForeignKey(ContentType,
|
||||
related_name='permission_holder',
|
||||
limit_choices_to = {'model__in': ('user', 'group', 'role')})
|
||||
holder_id = models.PositiveIntegerField()
|
||||
holder_object = generic.GenericForeignKey(ct_field='holder_type', fk_field='holder_id')
|
||||
|
||||
class Meta:
|
||||
verbose_name = _(u'permission holder')
|
||||
verbose_name_plural = _(u'permission holders')
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.holder_object)
|
||||
|
||||
|
||||
class Role(models.Model):
|
||||
name = models.CharField(max_length=64, unique=True)
|
||||
label = models.CharField(max_length=64, unique=True, verbose_name=_(u'label'))
|
||||
|
||||
class Meta:
|
||||
ordering = ('label',)
|
||||
verbose_name = _(u'role')
|
||||
verbose_name_plural = _(u'roles')
|
||||
|
||||
def add_member(self, member):
|
||||
role_member, created = RoleMember.objects.get_or_create(
|
||||
role=self,
|
||||
member_type = ContentType.objects.get_for_model(member),
|
||||
member_id=member.id)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.label
|
||||
|
||||
|
||||
class RoleMember(models.Model):
|
||||
role = models.ForeignKey(Role, verbose_name=_(u'role'))
|
||||
member_type = models.ForeignKey(ContentType,
|
||||
related_name='role_member',
|
||||
limit_choices_to = {'model__in': ('user', 'group', 'role')})
|
||||
member_id = models.PositiveIntegerField()
|
||||
member_object = generic.GenericForeignKey(ct_field='member_type', fk_field='member_id')
|
||||
|
||||
class Meta:
|
||||
#ordering = ('label',)
|
||||
verbose_name = _(u'role member')
|
||||
verbose_name_plural = _(u'role members')
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(self.member_object)
|
||||
0
apps/permissions/templatetags/__init__.py
Normal file
0
apps/permissions/templatetags/__init__.py
Normal file
37
apps/permissions/templatetags/permission_tags.py
Normal file
37
apps/permissions/templatetags/permission_tags.py
Normal file
@@ -0,0 +1,37 @@
|
||||
from django.template import TemplateSyntaxError, Library, \
|
||||
VariableDoesNotExist, Node, Variable
|
||||
|
||||
from permissions.api import check_permissions as check_permission_function, Unauthorized
|
||||
|
||||
register = Library()
|
||||
|
||||
|
||||
class CheckPermissionsNode(Node):
|
||||
def __init__(self, requester, namespace, permission_list, *args, **kwargs):
|
||||
self.requester = requester
|
||||
self.namespace = namespace
|
||||
self.permission_list = permission_list
|
||||
|
||||
def render(self, context):
|
||||
requester = Variable(self.requester).resolve(context)
|
||||
namespace = Variable(self.namespace).resolve(context)
|
||||
permission_list = Variable(self.permission_list).resolve(context)
|
||||
try:
|
||||
check_permission_function(requester, namespace, permission_list)
|
||||
context['permission'] = True
|
||||
return ''
|
||||
except Unauthorized:
|
||||
context['permission'] = False
|
||||
return ''
|
||||
|
||||
|
||||
@register.tag
|
||||
def check_permissions(parser, token):
|
||||
try:
|
||||
# Splitting by None == splitting by spaces.
|
||||
tag_name, args = token.contents.split(None, 1)
|
||||
except ValueError:
|
||||
raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
|
||||
|
||||
return CheckPermissionsNode(*args.split())
|
||||
|
||||
23
apps/permissions/tests.py
Normal file
23
apps/permissions/tests.py
Normal file
@@ -0,0 +1,23 @@
|
||||
"""
|
||||
This file demonstrates two different styles of tests (one doctest and one
|
||||
unittest). These will both pass when you run "manage.py test".
|
||||
|
||||
Replace these with more appropriate tests for your application.
|
||||
"""
|
||||
|
||||
from django.test import TestCase
|
||||
|
||||
class SimpleTest(TestCase):
|
||||
def test_basic_addition(self):
|
||||
"""
|
||||
Tests that 1 + 1 always equals 2.
|
||||
"""
|
||||
self.failUnlessEqual(1 + 1, 2)
|
||||
|
||||
__test__ = {"doctest": """
|
||||
Another way to test that 1 + 1 is equal to 2.
|
||||
|
||||
>>> 1 + 1 == 2
|
||||
True
|
||||
"""}
|
||||
|
||||
1
apps/permissions/views.py
Normal file
1
apps/permissions/views.py
Normal file
@@ -0,0 +1 @@
|
||||
# Create your views here.
|
||||
@@ -5,3 +5,4 @@
|
||||
* Changed to a liquid css grid
|
||||
* Added the ability to group documents by their metadata
|
||||
* New abstracted options to adjust document conversion quality (default, low, high)
|
||||
* Added permissions and roles support
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
* If theres only one document type on db skip step 1 of wizard - DONE
|
||||
* Be able to delete staging file - DONE
|
||||
* Group documents by metadata - DONE
|
||||
* Permissions - DONE
|
||||
* Roles - DONE
|
||||
* Document list filtering by metadata
|
||||
* Filterform date filtering widget
|
||||
* Validate GET data before saving file
|
||||
@@ -42,8 +44,6 @@
|
||||
* MuliThreading deferred OCR
|
||||
* Versioning support
|
||||
* Generic document anotations using layer overlays
|
||||
* Permissions
|
||||
* Roles
|
||||
* Workflows
|
||||
* Scheduled maintenance (cleanup, deferred OCR's)
|
||||
* Add tags to documents
|
||||
@@ -60,6 +60,6 @@
|
||||
* Support spreadsheets, wordprocessing docs using openoffice in server mode
|
||||
* WebDAV support
|
||||
* Handle ziped or rar archives
|
||||
* Display preferences (Rotation, default zoom)
|
||||
* Display preferences 'document transformations' (Rotation, default zoom)
|
||||
* Gallery view for document groups
|
||||
* Assign default role to new users
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
if [ -n "$1" ]; then
|
||||
./manage.py runserver_plus $1 --adminmedia ./site_media/admin_media/
|
||||
./manage.py runserver_plus $1 --adminmedia ./site_media/grappelli/
|
||||
else
|
||||
./manage.py runserver_plus --adminmedia ./site_media/admin_media/
|
||||
./manage.py runserver_plus --adminmedia ./site_media/grappelli/
|
||||
fi
|
||||
|
||||
@@ -77,7 +77,7 @@ MEDIA_URL = '/%s-site_media/' % PROJECT_NAME
|
||||
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
|
||||
# trailing slash.
|
||||
# Examples: "http://foo.com/media/", "/media/".
|
||||
ADMIN_MEDIA_PREFIX = MEDIA_URL + 'admin_media/'
|
||||
ADMIN_MEDIA_PREFIX = MEDIA_URL + 'grappelli/'
|
||||
|
||||
# Make this unique, and don't share it with anybody.
|
||||
SECRET_KEY = 'om^a(i8^6&h+umbd2%pt91cj!qu_@oztw117rgxmn(n2lp^*c!'
|
||||
@@ -215,6 +215,9 @@ LOGIN_EXEMPT_URLS = (
|
||||
# OCR
|
||||
#OCR_TESSERACT_PATH = u'/usr/bin/tesseract'
|
||||
|
||||
# Permissions
|
||||
#ROLES_DEFAULT_ROLES = []
|
||||
|
||||
# Override
|
||||
SEARCH_SHOW_OBJECT_TYPE = False
|
||||
#======== End of configuration options =======
|
||||
|
||||
Reference in New Issue
Block a user