PEP8 cleanups.
This commit is contained in:
@@ -10,7 +10,9 @@ from .permissions import permission_acl_view, permission_acl_edit
|
||||
|
||||
def get_kwargs_factory(variable_name):
|
||||
def get_kwargs(context):
|
||||
content_type = ContentType.objects.get_for_model(context[variable_name])
|
||||
content_type = ContentType.objects.get_for_model(
|
||||
context[variable_name]
|
||||
)
|
||||
return {
|
||||
'app_label': '"{}"'.format(content_type.app_label),
|
||||
'model': '"{}"'.format(content_type.model),
|
||||
|
||||
@@ -2,7 +2,9 @@ from __future__ import unicode_literals
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import ACLCreateView, ACLDeleteView, ACLListView, ACLPermissionsView
|
||||
from .views import (
|
||||
ACLCreateView, ACLDeleteView, ACLListView, ACLPermissionsView
|
||||
)
|
||||
|
||||
urlpatterns = patterns(
|
||||
'acls.views',
|
||||
|
||||
@@ -11,6 +11,7 @@ from ..settings import setting_login_method
|
||||
TEST_ADMIN_EMAIL = 'admin@admin.com'
|
||||
TEST_ADMIN_PASSWORD = 'test_admin_password'
|
||||
TEST_ADMIN_USERNAME = 'test_admin'
|
||||
TEST_EMAIL_AUTHENTICATION_BACKEND = 'authentication.auth.email_auth_backend.EmailAuthBackend'
|
||||
|
||||
|
||||
class UserLoginTestCase(TestCase):
|
||||
@@ -43,7 +44,7 @@ class UserLoginTestCase(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_email_login(self):
|
||||
with self.settings(AUTHENTICATION_BACKENDS=('authentication.auth.email_auth_backend.EmailAuthBackend',)):
|
||||
with self.settings(AUTHENTICATION_BACKENDS=(TEST_EMAIL_AUTHENTICATION_BACKEND,)):
|
||||
setting_login_method.value = 'email'
|
||||
|
||||
logged_in = self.client.login(
|
||||
@@ -78,7 +79,7 @@ class UserLoginTestCase(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_email_login_via_views(self):
|
||||
with self.settings(AUTHENTICATION_BACKENDS=('authentication.auth.email_auth_backend.EmailAuthBackend',)):
|
||||
with self.settings(AUTHENTICATION_BACKENDS=(TEST_EMAIL_AUTHENTICATION_BACKEND,)):
|
||||
setting_login_method.value = 'email'
|
||||
response = self.client.get(reverse('documents:document_list'))
|
||||
self.assertRedirects(
|
||||
|
||||
@@ -118,7 +118,9 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView):
|
||||
filtered_documents = documents
|
||||
|
||||
return DocumentCheckout.objects.filter(
|
||||
document__pk__in=filtered_documents.values_list('pk', flat=True)
|
||||
document__pk__in=filtered_documents.values_list(
|
||||
'pk', flat=True
|
||||
)
|
||||
)
|
||||
elif self.request.method == 'DELETE':
|
||||
return DocumentCheckout.objects.all()
|
||||
@@ -155,7 +157,10 @@ class APICheckedoutDocumentView(generics.RetrieveDestroyAPIView):
|
||||
)
|
||||
except PermissionDenied:
|
||||
AccessControlList.objects.check_access(
|
||||
permission_document_checkin_override, request.user, document
|
||||
permission_document_checkin_override, request.user,
|
||||
document
|
||||
)
|
||||
|
||||
return super(APICheckedoutDocumentView, self).delete(request, *args, **kwargs)
|
||||
return super(
|
||||
APICheckedoutDocumentView, self
|
||||
).delete(request, *args, **kwargs)
|
||||
|
||||
@@ -10,6 +10,7 @@ def check_if_new_versions_allowed(sender, **kwargs):
|
||||
if not DocumentCheckout.objects.are_document_new_versions_allowed(kwargs['instance'].document):
|
||||
raise NewDocumentVersionNotAllowed(
|
||||
_(
|
||||
'New versions not allowed for the checkedout document: %s' % kwargs['instance'].document
|
||||
'New versions not allowed for the checkedout document: %s'
|
||||
% kwargs['instance'].document
|
||||
)
|
||||
)
|
||||
|
||||
@@ -15,13 +15,53 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='DocumentCheckout',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('checkout_datetime', models.DateTimeField(auto_now_add=True, verbose_name='Check out date and time')),
|
||||
('expiration_datetime', models.DateTimeField(help_text='Amount of time to hold the document checked out in minutes.', verbose_name='Check out expiration date and time')),
|
||||
('user_object_id', models.PositiveIntegerField(null=True, blank=True)),
|
||||
('block_new_version', models.BooleanField(default=True, help_text='Do not allow new version of this document to be uploaded.', verbose_name='Block new version upload')),
|
||||
('document', models.ForeignKey(verbose_name='Document', to='documents.Document', unique=True)),
|
||||
('user_content_type', models.ForeignKey(blank=True, to='contenttypes.ContentType', null=True)),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'checkout_datetime',
|
||||
models.DateTimeField(
|
||||
auto_now_add=True,
|
||||
verbose_name='Check out date and time'
|
||||
)
|
||||
),
|
||||
(
|
||||
'expiration_datetime',
|
||||
models.DateTimeField(
|
||||
help_text='Amount of time to hold the document '
|
||||
'checked out in minutes.',
|
||||
verbose_name='Check out expiration date and time'
|
||||
)
|
||||
),
|
||||
(
|
||||
'user_object_id',
|
||||
models.PositiveIntegerField(null=True, blank=True)
|
||||
),
|
||||
(
|
||||
'block_new_version',
|
||||
models.BooleanField(
|
||||
default=True,
|
||||
help_text='Do not allow new version of this document '
|
||||
'to be uploaded.',
|
||||
verbose_name='Block new version upload'
|
||||
)
|
||||
),
|
||||
(
|
||||
'document',
|
||||
models.ForeignKey(
|
||||
verbose_name='Document', to='documents.Document',
|
||||
unique=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'user_content_type',
|
||||
models.ForeignKey(
|
||||
blank=True, to='contenttypes.ContentType', null=True
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Document checkout',
|
||||
|
||||
@@ -16,7 +16,10 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='documentcheckout',
|
||||
name='user',
|
||||
field=models.ForeignKey(verbose_name='User', blank=True, to=settings.AUTH_USER_MODEL, null=True),
|
||||
field=models.ForeignKey(
|
||||
verbose_name='User', blank=True, to=settings.AUTH_USER_MODEL,
|
||||
null=True
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -23,5 +23,7 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(move_from_content_type_user_to_foreign_key_field_user),
|
||||
migrations.RunPython(
|
||||
move_from_content_type_user_to_foreign_key_field_user
|
||||
),
|
||||
]
|
||||
|
||||
@@ -23,7 +23,9 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='documentcheckout',
|
||||
name='user',
|
||||
field=models.ForeignKey(verbose_name='User', to=settings.AUTH_USER_MODEL),
|
||||
field=models.ForeignKey(
|
||||
verbose_name='User', to=settings.AUTH_USER_MODEL
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -11,7 +11,8 @@ from common.literals import TIME_DELTA_UNIT_CHOICES
|
||||
|
||||
class SplitTimeDeltaWidget(forms.widgets.MultiWidget):
|
||||
"""
|
||||
A Widget that splits a timedelta input into three <input type="text"> boxes.
|
||||
A Widget that splits a timedelta input into three <input type="text">
|
||||
boxes.
|
||||
"""
|
||||
|
||||
def __init__(self, attrs=None):
|
||||
|
||||
@@ -18,8 +18,8 @@ class ModelAttribute(object):
|
||||
|
||||
return result
|
||||
except IndexError:
|
||||
# We were passed a model instance, try again using the model of the
|
||||
# instance
|
||||
# We were passed a model instance, try again using the model of
|
||||
# the instance
|
||||
|
||||
# If we are already in the model class, exit with an error
|
||||
if model.__class__ == models.base.ModelBase:
|
||||
@@ -30,16 +30,24 @@ class ModelAttribute(object):
|
||||
@classmethod
|
||||
def get_choices_for(cls, model, type_names=None):
|
||||
return [
|
||||
(attribute.name, attribute) for attribute in cls.get_for(model, type_names)
|
||||
(
|
||||
attribute.name, attribute
|
||||
) for attribute in cls.get_for(model, type_names)
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def help_text_for(cls, model, type_names=None):
|
||||
result = []
|
||||
for count, attribute in enumerate(cls.get_for(model, type_names), 1):
|
||||
result.append('{}) {}'.format(count, unicode(attribute.get_display(show_name=True))))
|
||||
result.append(
|
||||
'{}) {}'.format(
|
||||
count, unicode(attribute.get_display(show_name=True))
|
||||
)
|
||||
)
|
||||
|
||||
return ' '.join([ugettext('Available attributes: '), ', '.join(result)])
|
||||
return ' '.join(
|
||||
[ugettext('Available attributes: '), ', '.join(result)]
|
||||
)
|
||||
|
||||
def get_display(self, show_name=False):
|
||||
if self.description:
|
||||
|
||||
@@ -101,7 +101,9 @@ class CompressedFile(object):
|
||||
filename for filename in zfobj.namelist() if not filename.endswith('/')
|
||||
]
|
||||
return (
|
||||
SimpleUploadedFile(name=filename, content=zfobj.read(filename)) for filename in filenames
|
||||
SimpleUploadedFile(
|
||||
name=filename, content=zfobj.read(filename)
|
||||
) for filename in filenames
|
||||
)
|
||||
except zipfile.BadZipfile:
|
||||
raise NotACompressedFile
|
||||
|
||||
@@ -54,7 +54,9 @@ class DetailForm(forms.ModelForm):
|
||||
self.fields[field_name].help_text = ''
|
||||
|
||||
for field_name, field in self.fields.items():
|
||||
self.fields[field_name].widget.attrs.update({'readonly': 'readonly'})
|
||||
self.fields[field_name].widget.attrs.update(
|
||||
{'readonly': 'readonly'}
|
||||
)
|
||||
|
||||
|
||||
class ChoiceForm(forms.Form):
|
||||
|
||||
@@ -4,11 +4,9 @@ from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
from django.http import Http404, HttpResponseRedirect
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import FormView, TemplateView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||
from django.views.generic.list import ListView
|
||||
|
||||
@@ -110,7 +108,9 @@ class AssignRemoveView(ExtraContextMixin, ViewPermissionCheckMixin, ObjectPermis
|
||||
label = dict(flat_list)[selection]
|
||||
if self.decode_content_type:
|
||||
model, pk = selection.split(',')
|
||||
selection_obj = ContentType.objects.get(model=model).get_object_for_this_type(pk=pk)
|
||||
selection_obj = ContentType.objects.get(
|
||||
model=model
|
||||
).get_object_for_this_type(pk=pk)
|
||||
else:
|
||||
selection_obj = selection
|
||||
|
||||
@@ -202,7 +202,9 @@ class MultiFormView(FormView):
|
||||
def get_forms(self, form_classes):
|
||||
return dict(
|
||||
[
|
||||
(key, self._create_form(key, klass)) for key, klass in form_classes.items()
|
||||
(
|
||||
key, self._create_form(key, klass)
|
||||
) for key, klass in form_classes.items()
|
||||
]
|
||||
)
|
||||
|
||||
@@ -270,7 +272,9 @@ class SingleObjectCreateView(ViewPermissionCheckMixin, ExtraContextMixin, Redire
|
||||
try:
|
||||
messages.success(
|
||||
self.request,
|
||||
_('%s created successfully.') % self.extra_context['object_name'].capitalize()
|
||||
_(
|
||||
'%s created successfully.'
|
||||
) % self.extra_context['object_name'].capitalize()
|
||||
)
|
||||
except KeyError:
|
||||
messages.success(
|
||||
@@ -294,7 +298,8 @@ class SingleObjectDeleteView(ViewPermissionCheckMixin, ObjectPermissionCheckMixi
|
||||
except Exception as exception:
|
||||
try:
|
||||
messages.error(
|
||||
self.request, _('Error deleting %s.') % self.extra_context['object_name']
|
||||
self.request,
|
||||
_('Error deleting %s.') % self.extra_context['object_name']
|
||||
)
|
||||
except KeyError:
|
||||
messages.error(
|
||||
@@ -305,7 +310,10 @@ class SingleObjectDeleteView(ViewPermissionCheckMixin, ObjectPermissionCheckMixi
|
||||
else:
|
||||
try:
|
||||
messages.success(
|
||||
self.request, _('%s deleted successfully.') % self.extra_context['object_name'].capitalize()
|
||||
self.request,
|
||||
_(
|
||||
'%s deleted successfully.'
|
||||
) % self.extra_context['object_name'].capitalize()
|
||||
)
|
||||
except KeyError:
|
||||
messages.success(
|
||||
@@ -325,7 +333,10 @@ class SingleObjectEditView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin,
|
||||
|
||||
try:
|
||||
messages.error(
|
||||
self.request, _('Error saving %s details.') % self.extra_context['object_name']
|
||||
self.request,
|
||||
_(
|
||||
'Error saving %s details.'
|
||||
) % self.extra_context['object_name']
|
||||
)
|
||||
except KeyError:
|
||||
messages.error(
|
||||
@@ -339,7 +350,10 @@ class SingleObjectEditView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin,
|
||||
|
||||
try:
|
||||
messages.success(
|
||||
self.request, _('%s details saved successfully.') % self.extra_context['object_name'].capitalize()
|
||||
self.request,
|
||||
_(
|
||||
'%s details saved successfully.'
|
||||
) % self.extra_context['object_name'].capitalize()
|
||||
)
|
||||
except KeyError:
|
||||
messages.success(
|
||||
@@ -354,4 +368,3 @@ class SingleObjectListView(PaginationMixin, ViewPermissionCheckMixin, ObjectList
|
||||
|
||||
def get_paginate_by(self, queryset):
|
||||
return setting_paginate_by.value
|
||||
|
||||
|
||||
@@ -8,5 +8,7 @@ class AjaxRedirect(object):
|
||||
def process_response(self, request, response):
|
||||
if request.is_ajax():
|
||||
if type(response) == HttpResponseRedirect:
|
||||
response.status_code = getattr(settings, 'AJAX_REDIRECT_CODE', 302)
|
||||
response.status_code = getattr(
|
||||
settings, 'AJAX_REDIRECT_CODE', 302
|
||||
)
|
||||
return response
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -49,7 +49,8 @@ class ObjectListPermissionFilterMixin(object):
|
||||
self.request.user, (self.object_permission,)
|
||||
)
|
||||
except PermissionDenied:
|
||||
# No global permission, filter ther queryset per object + permission
|
||||
# No global permission, filter ther queryset per object +
|
||||
# permission
|
||||
return AccessControlList.objects.filter_by_access(
|
||||
self.object_permission, self.request.user, queryset
|
||||
)
|
||||
@@ -79,7 +80,9 @@ class ObjectPermissionCheckMixin(object):
|
||||
self.get_permission_object()
|
||||
)
|
||||
|
||||
return super(ObjectPermissionCheckMixin, self).dispatch(request, *args, **kwargs)
|
||||
return super(
|
||||
ObjectPermissionCheckMixin, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class RedirectionMixin(object):
|
||||
@@ -111,7 +114,9 @@ class RedirectionMixin(object):
|
||||
)
|
||||
)
|
||||
|
||||
return super(RedirectionMixin, self).dispatch(request, *args, **kwargs)
|
||||
return super(
|
||||
RedirectionMixin, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RedirectionMixin, self).get_context_data(**kwargs)
|
||||
@@ -137,4 +142,6 @@ class ViewPermissionCheckMixin(object):
|
||||
self.request.user, (self.view_permission,)
|
||||
)
|
||||
|
||||
return super(ViewPermissionCheckMixin, self).dispatch(request, *args, **kwargs)
|
||||
return super(
|
||||
ViewPermissionCheckMixin, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
|
||||
@@ -9,7 +9,11 @@ from smart_settings import Namespace
|
||||
namespace = Namespace(name='common', label=_('Common'))
|
||||
setting_temporary_directory = namespace.add_setting(
|
||||
global_name='COMMON_TEMPORARY_DIRECTORY', default=tempfile.gettempdir(),
|
||||
help_text=_('Temporary directory used site wide to store thumbnails, previews and temporary files. If none is specified, one will be created using tempfile.mkdtemp()'),
|
||||
help_text=_(
|
||||
'Temporary directory used site wide to store thumbnails, previews '
|
||||
'and temporary files. If none is specified, one will be created '
|
||||
'using tempfile.mkdtemp()'
|
||||
),
|
||||
is_path=True
|
||||
)
|
||||
setting_shared_storage = namespace.add_setting(
|
||||
@@ -20,5 +24,7 @@ setting_shared_storage = namespace.add_setting(
|
||||
setting_paginate_by = namespace.add_setting(
|
||||
global_name='COMMON_PAGINATE_BY',
|
||||
default=40,
|
||||
help_text=_('An integer specifying how many objects should be displayed per page.')
|
||||
help_text=_(
|
||||
'An integer specifying how many objects should be displayed per page.'
|
||||
)
|
||||
)
|
||||
|
||||
@@ -100,7 +100,9 @@ def return_attrib(obj, attrib, arguments=None):
|
||||
try:
|
||||
if isinstance(attrib, types.FunctionType):
|
||||
return attrib(obj)
|
||||
elif isinstance(obj, types.DictType) or isinstance(obj, types.DictionaryType):
|
||||
elif isinstance(
|
||||
obj, types.DictType
|
||||
) or isinstance(obj, types.DictionaryType):
|
||||
return obj[attrib]
|
||||
else:
|
||||
result = reduce(getattr, attrib.split('.'), obj)
|
||||
@@ -140,12 +142,13 @@ def urlquote(link=None, get=None):
|
||||
|
||||
assert link or get
|
||||
if isinstance(link, dict):
|
||||
# urlqoute({'key': 'value', 'key2': 'value2'}) --> key=value&key2=value2
|
||||
# urlqoute({'key': 'value', 'key2': 'value2'}) -->
|
||||
# key=value&key2=value2
|
||||
assert not get, get
|
||||
get = link
|
||||
link = ''
|
||||
assert isinstance(get, dict), 'wrong type "%s", dict required' % type(get)
|
||||
# assert not (link.startswith('http://') or link.startswith('https://')), \
|
||||
# assert not (link.startswith('http://') or link.startswith('https://')),
|
||||
# 'This method should only quote the url path.
|
||||
# It should not start with http(s):// (%s)' % (
|
||||
# link)
|
||||
|
||||
@@ -12,9 +12,6 @@ from django.utils.http import urlencode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from documents.search import document_search
|
||||
|
||||
from .classes import MissingItem
|
||||
from .forms import (
|
||||
LicenseForm, LocaleProfileForm, LocaleProfileForm_view,
|
||||
UserForm, UserForm_view
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from itertools import chain
|
||||
import os
|
||||
|
||||
from django import forms
|
||||
@@ -107,50 +106,6 @@ class PlainWidget(forms.widgets.Widget):
|
||||
return mark_safe('%s' % value)
|
||||
|
||||
|
||||
class ScrollableCheckboxSelectMultiple(forms.widgets.CheckboxSelectMultiple):
|
||||
"""
|
||||
Class for a form widget composed of a selection of checkboxes wrapped
|
||||
in a div tag with automatic overflow to add scrollbars when the list
|
||||
exceds the height of the div
|
||||
"""
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
if value is None:
|
||||
value = []
|
||||
has_id = attrs and 'id' in attrs
|
||||
final_attrs = self.build_attrs(attrs, name=name)
|
||||
# TODO: Move this styling to a CSS class
|
||||
output = [
|
||||
'<ul class="undecorated_list" style="margin-left: 5px; margin-top: 3px; margin-bottom: 3px;">'
|
||||
]
|
||||
# Normalize to strings
|
||||
str_values = set([force_unicode(v) for v in value])
|
||||
for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
|
||||
# If an ID attribute was given, add a numeric index as a suffix,
|
||||
# so that the checkboxes don't all have the same ID attribute.
|
||||
if has_id:
|
||||
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
|
||||
label_for = ' for="%s"' % final_attrs['id']
|
||||
else:
|
||||
label_for = ''
|
||||
|
||||
cb = forms.widgets.CheckboxInput(
|
||||
final_attrs, check_test=lambda value: value in str_values
|
||||
)
|
||||
option_value = force_unicode(option_value)
|
||||
rendered_cb = cb.render(name, option_value)
|
||||
option_label = conditional_escape(force_unicode(option_label))
|
||||
output.append(
|
||||
'<li><label%s>%s %s</label></li>' % (
|
||||
label_for, rendered_cb, option_label
|
||||
)
|
||||
)
|
||||
output.append('</ul>')
|
||||
|
||||
return mark_safe(
|
||||
'<div class="text_area_div">%s</div>' % '\n'.join(output)
|
||||
)
|
||||
|
||||
|
||||
class TextAreaDiv(forms.widgets.Widget):
|
||||
"""
|
||||
Class to define a form widget that simulates the behavior of a
|
||||
|
||||
@@ -32,7 +32,9 @@ class DjangoGPGTestCase(TestCase):
|
||||
|
||||
# Test querying the keyservers
|
||||
self.assertTrue(
|
||||
TEST_KEY_ID in [key_stub.key_id for key_stub in self.gpg.query(TEST_UIDS)]
|
||||
TEST_KEY_ID in [
|
||||
key_stub.key_id for key_stub in self.gpg.query(TEST_UIDS)
|
||||
]
|
||||
)
|
||||
|
||||
# Receive a public key from the keyserver
|
||||
@@ -40,5 +42,7 @@ class DjangoGPGTestCase(TestCase):
|
||||
|
||||
# Check that the received key is indeed in the keyring
|
||||
self.assertTrue(
|
||||
TEST_KEY_ID[-16:] in [key_stub.key_id for key_stub in Key.get_all(self.gpg)]
|
||||
TEST_KEY_ID[-16:] in [
|
||||
key_stub.key_id for key_stub in Key.get_all(self.gpg)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from datetime import datetime
|
||||
import logging
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
@@ -51,10 +51,16 @@ def comment_delete(request, comment_id=None, comment_id_list=None):
|
||||
)
|
||||
|
||||
previous = request.POST.get(
|
||||
'previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))
|
||||
'previous', request.GET.get(
|
||||
'previous', request.META.get(
|
||||
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
|
||||
)
|
||||
)
|
||||
)
|
||||
next = request.POST.get(
|
||||
'next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))
|
||||
'next', request.GET.get(
|
||||
'next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))
|
||||
)
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
@@ -110,7 +116,11 @@ def comment_add(request, document_id):
|
||||
|
||||
post_action_redirect = None
|
||||
|
||||
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
||||
next = request.POST.get(
|
||||
'next', request.GET.get(
|
||||
'next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))
|
||||
)
|
||||
)
|
||||
|
||||
if request.method == 'POST':
|
||||
form = CommentForm(request.POST)
|
||||
@@ -144,7 +154,8 @@ class DocumentCommentListView(SingleObjectListView):
|
||||
)
|
||||
except PermissionDenied:
|
||||
AccessControlList.objects.check_access(
|
||||
permission_comment_view, self.request.user, self.get_document()
|
||||
permission_comment_view, self.request.user,
|
||||
self.get_document()
|
||||
)
|
||||
|
||||
return self.get_document().comments.all()
|
||||
|
||||
@@ -61,7 +61,8 @@ class DocumentIndexingApp(MayanAppConfig):
|
||||
)
|
||||
)
|
||||
SourceColumn(
|
||||
source=IndexInstance, label=_('Document types'), attribute='get_document_types_names'
|
||||
source=IndexInstance, label=_('Document types'),
|
||||
attribute='get_document_types_names'
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
@@ -74,7 +75,9 @@ class DocumentIndexingApp(MayanAppConfig):
|
||||
)
|
||||
SourceColumn(
|
||||
source=IndexTemplateNode, label=_('Has document links?'),
|
||||
func=lambda context: two_state_template(context['object'].link_documents)
|
||||
func=lambda context: two_state_template(
|
||||
context['object'].link_documents
|
||||
)
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
|
||||
@@ -20,7 +20,8 @@ class IndexInstanceNodeManager(models.Manager):
|
||||
@staticmethod
|
||||
def delete_empty_index_nodes_recursive(instance_node):
|
||||
"""
|
||||
Calls itself recursively deleting empty index instance nodes up to root
|
||||
Calls itself recursively deleting empty index instance nodes up to
|
||||
root
|
||||
"""
|
||||
|
||||
if instance_node.get_children().count() == 0:
|
||||
|
||||
@@ -15,11 +15,38 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='Index',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('name', models.CharField(help_text='Internal name used to reference this index.', unique=True, max_length=64, verbose_name='Name')),
|
||||
('title', models.CharField(help_text='The name that will be visible to users.', unique=True, max_length=128, verbose_name='Title')),
|
||||
('enabled', models.BooleanField(default=True, help_text='Causes this index to be visible and updated when document data changes.', verbose_name='Enabled')),
|
||||
('document_types', models.ManyToManyField(to='documents.DocumentType', verbose_name='Document types')),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'name', models.CharField(
|
||||
help_text='Internal name used to reference this index.',
|
||||
unique=True, max_length=64, verbose_name='Name'
|
||||
)
|
||||
),
|
||||
(
|
||||
'title', models.CharField(
|
||||
help_text='The name that will be visible to users.',
|
||||
unique=True, max_length=128, verbose_name='Title'
|
||||
)
|
||||
),
|
||||
(
|
||||
'enabled', models.BooleanField(
|
||||
default=True,
|
||||
help_text='Causes this index to be visible and updated when document data changes.',
|
||||
verbose_name='Enabled'
|
||||
)
|
||||
),
|
||||
(
|
||||
'document_types',
|
||||
models.ManyToManyField(
|
||||
to='documents.DocumentType',
|
||||
verbose_name='Document types'
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Index',
|
||||
@@ -30,13 +57,43 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='IndexInstanceNode',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('value', models.CharField(max_length=128, verbose_name='Value', blank=True)),
|
||||
('lft', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('rght', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('level', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('documents', models.ManyToManyField(related_name='node_instances', verbose_name='Documents', to='documents.Document')),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'value', models.CharField(
|
||||
max_length=128, verbose_name='Value', blank=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'lft', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'rght', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'tree_id', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'level', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'documents', models.ManyToManyField(
|
||||
related_name='node_instances',
|
||||
verbose_name='Documents', to='documents.Document'
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Index node instance',
|
||||
@@ -47,16 +104,64 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='IndexTemplateNode',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
||||
('expression', models.CharField(help_text='Enter a python string expression to be evaluated.', max_length=128, verbose_name='Indexing expression')),
|
||||
('enabled', models.BooleanField(default=True, help_text='Causes this node to be visible and updated when document data changes.', verbose_name='Enabled')),
|
||||
('link_documents', models.BooleanField(default=False, help_text='Check this option to have this node act as a container for documents and not as a parent for further nodes.', verbose_name='Link documents')),
|
||||
('lft', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('rght', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('tree_id', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('level', models.PositiveIntegerField(editable=False, db_index=True)),
|
||||
('index', models.ForeignKey(related_name='node_templates', verbose_name='Index', to='document_indexing.Index')),
|
||||
('parent', mptt.fields.TreeForeignKey(blank=True, to='document_indexing.IndexTemplateNode', null=True)),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'expression', models.CharField(
|
||||
help_text='Enter a python string expression to be evaluated.',
|
||||
max_length=128, verbose_name='Indexing expression'
|
||||
)
|
||||
),
|
||||
(
|
||||
'enabled', models.BooleanField(
|
||||
default=True,
|
||||
help_text='Causes this node to be visible and updated when document data changes.',
|
||||
verbose_name='Enabled'
|
||||
)
|
||||
),
|
||||
(
|
||||
'link_documents', models.BooleanField(
|
||||
default=False,
|
||||
help_text='Check this option to have this node act as a container for documents and not as a parent for further nodes.',
|
||||
verbose_name='Link documents'
|
||||
)
|
||||
),
|
||||
(
|
||||
'lft', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'rght', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'tree_id', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'level', models.PositiveIntegerField(
|
||||
editable=False, db_index=True
|
||||
)
|
||||
),
|
||||
(
|
||||
'index', models.ForeignKey(
|
||||
related_name='node_templates', verbose_name='Index',
|
||||
to='document_indexing.Index'
|
||||
)
|
||||
),
|
||||
(
|
||||
'parent', mptt.fields.TreeForeignKey(
|
||||
blank=True, to='document_indexing.IndexTemplateNode',
|
||||
null=True
|
||||
)
|
||||
),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Index node template',
|
||||
@@ -67,13 +172,20 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='indexinstancenode',
|
||||
name='index_template_node',
|
||||
field=models.ForeignKey(related_name='node_instance', verbose_name='Index template node', to='document_indexing.IndexTemplateNode'),
|
||||
field=models.ForeignKey(
|
||||
related_name='node_instance',
|
||||
verbose_name='Index template node',
|
||||
to='document_indexing.IndexTemplateNode'
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='indexinstancenode',
|
||||
name='parent',
|
||||
field=mptt.fields.TreeForeignKey(blank=True, to='document_indexing.IndexInstanceNode', null=True),
|
||||
field=mptt.fields.TreeForeignKey(
|
||||
blank=True, to='document_indexing.IndexInstanceNode',
|
||||
null=True
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,9 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='index',
|
||||
name='label',
|
||||
field=models.CharField(unique=True, max_length=128, verbose_name='Label'),
|
||||
field=models.CharField(
|
||||
unique=True, max_length=128, verbose_name='Label'
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,11 @@ class Migration(migrations.Migration):
|
||||
migrations.AddField(
|
||||
model_name='index',
|
||||
name='slug',
|
||||
field=models.SlugField(null=True, max_length=128, blank=True, help_text='This values will be used by other apps to reference this index.', unique=True, verbose_name='Slug'),
|
||||
field=models.SlugField(
|
||||
null=True, max_length=128, blank=True,
|
||||
help_text='This values will be used by other apps to reference this index.',
|
||||
unique=True, verbose_name='Slug'
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,11 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='index',
|
||||
name='slug',
|
||||
field=models.SlugField(default='', max_length=128, help_text='This values will be used by other apps to reference this index.', unique=True, verbose_name='Slug'),
|
||||
field=models.SlugField(
|
||||
default='', max_length=128,
|
||||
help_text='This values will be used by other apps to reference this index.',
|
||||
unique=True, verbose_name='Slug'
|
||||
),
|
||||
preserve_default=False,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,10 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='indexinstancenode',
|
||||
name='value',
|
||||
field=models.CharField(db_index=True, max_length=128, verbose_name='Value', blank=True),
|
||||
field=models.CharField(
|
||||
db_index=True, max_length=128, verbose_name='Value',
|
||||
blank=True
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -14,7 +14,10 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='indextemplatenode',
|
||||
name='expression',
|
||||
field=models.CharField(help_text="Enter a template to render. Use Django's default templating language (https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)", max_length=128, verbose_name='Indexing expression'),
|
||||
field=models.CharField(
|
||||
help_text="Enter a template to render. Use Django's default templating language (https://docs.djangoproject.com/en/1.7/ref/templates/builtins/)",
|
||||
max_length=128, verbose_name='Indexing expression'
|
||||
),
|
||||
preserve_default=True,
|
||||
),
|
||||
]
|
||||
|
||||
@@ -71,7 +71,9 @@ class Index(models.Model):
|
||||
|
||||
def get_document_types_names(self):
|
||||
return ', '.join(
|
||||
[unicode(document_type) for document_type in self.document_types.all()] or ['None']
|
||||
[
|
||||
unicode(document_type) for document_type in self.document_types.all()
|
||||
] or ['None']
|
||||
)
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -37,7 +37,8 @@ urlpatterns = patterns(
|
||||
),
|
||||
url(
|
||||
r'^setup/index/(?P<pk>\d+)/document_types/$',
|
||||
SetupIndexDocumentTypesView.as_view(), name='index_setup_document_types'
|
||||
SetupIndexDocumentTypesView.as_view(),
|
||||
name='index_setup_document_types'
|
||||
),
|
||||
url(
|
||||
r'^setup/template/node/(?P<parent_pk>\d+)/create/child/$',
|
||||
@@ -84,8 +85,8 @@ api_urls = patterns(
|
||||
name='index-detail'
|
||||
),
|
||||
url(
|
||||
r'^index/(?P<pk>[0-9]+)/template/$', APIIndexTemplateListView.as_view(),
|
||||
name='index-template-detail'
|
||||
r'^index/(?P<pk>[0-9]+)/template/$',
|
||||
APIIndexTemplateListView.as_view(), name='index-template-detail'
|
||||
),
|
||||
url(r'^indexes/$', APIIndexListView.as_view(), name='index-list'),
|
||||
url(
|
||||
|
||||
@@ -15,7 +15,6 @@ from common.views import (
|
||||
AssignRemoveView, SingleObjectCreateView, SingleObjectDeleteView,
|
||||
SingleObjectEditView, SingleObjectListView
|
||||
)
|
||||
from common.widgets import two_state_template
|
||||
from documents.models import Document, DocumentType
|
||||
from documents.permissions import permission_document_view
|
||||
from documents.views import DocumentListView
|
||||
@@ -33,7 +32,7 @@ from .permissions import (
|
||||
permission_document_indexing_setup, permission_document_indexing_view
|
||||
)
|
||||
from .tasks import task_do_rebuild_all_indexes
|
||||
from .widgets import index_instance_item_link, get_breadcrumbs, node_level
|
||||
from .widgets import get_breadcrumbs
|
||||
|
||||
|
||||
# Setup views
|
||||
|
||||
@@ -21,7 +21,9 @@ def get_instance_link(index_instance_node, text=None, simple=False):
|
||||
|
||||
return template % {
|
||||
'url': index_instance_node.get_absolute_url(),
|
||||
'value': text if text else (index_instance_node if index_instance_node.parent else index_instance_node.index_template_node.index)
|
||||
'value': text if text else (
|
||||
index_instance_node if index_instance_node.parent else index_instance_node.index_template_node.index
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +52,9 @@ def get_breadcrumbs(index_instance_node, simple=False, single_link=False, includ
|
||||
# Return the entire breadcrumb path as a single HTML anchor
|
||||
output.insert(
|
||||
0, get_instance_link(
|
||||
index_instance_node=index_instance_node, text=(' / '.join(result))
|
||||
index_instance_node=index_instance_node, text=(
|
||||
' / '.join(result)
|
||||
)
|
||||
)
|
||||
)
|
||||
return mark_safe(' '.join(output))
|
||||
@@ -68,11 +72,13 @@ def index_instance_item_link(index_instance_item):
|
||||
else:
|
||||
icon_template = ''
|
||||
|
||||
return mark_safe('%(icon_template)s <a href="%(url)s">%(text)s</a>' % {
|
||||
'url': index_instance_item.get_absolute_url(),
|
||||
'icon_template': icon_template,
|
||||
'text': index_instance_item
|
||||
})
|
||||
return mark_safe(
|
||||
'%(icon_template)s <a href="%(url)s">%(text)s</a>' % {
|
||||
'url': index_instance_item.get_absolute_url(),
|
||||
'icon_template': icon_template,
|
||||
'text': index_instance_item
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def node_level(node):
|
||||
@@ -83,8 +89,9 @@ def node_level(node):
|
||||
return mark_safe(
|
||||
''.join(
|
||||
[
|
||||
' ' * (getattr(node, node._mptt_meta.level_attr) - 1),
|
||||
'' if node.is_root_node() else '<i class="fa fa-level-up fa-rotate-90"></i> ',
|
||||
' ' * (
|
||||
getattr(node, node._mptt_meta.level_attr) - 1
|
||||
), '' if node.is_root_node() else '<i class="fa fa-level-up fa-rotate-90"></i> ',
|
||||
ugettext('Root') if node.is_root_node() else unicode(node)
|
||||
]
|
||||
)
|
||||
|
||||
@@ -103,15 +103,6 @@ class PrintForm(forms.Form):
|
||||
page_range = forms.CharField(label=_('Page range'), required=False)
|
||||
|
||||
|
||||
class DocumentTypeFilenameForm(forms.ModelForm):
|
||||
"""
|
||||
Model class form to edit a document type filename
|
||||
"""
|
||||
class Meta:
|
||||
fields = ('filename', 'enabled')
|
||||
model = DocumentTypeFilename
|
||||
|
||||
|
||||
class DocumentTypeFilenameForm_create(forms.ModelForm):
|
||||
"""
|
||||
Model class form to create a new document type filename
|
||||
|
||||
@@ -1 +1 @@
|
||||
from .literals import *
|
||||
from .literals import * # NOQA
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.files import File
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
@@ -21,8 +21,7 @@ from common.generics import (
|
||||
SingleObjectEditView, SingleObjectListView
|
||||
)
|
||||
from common.mixins import MultipleInstanceActionMixin
|
||||
from common.utils import encapsulate, pretty_size
|
||||
from common.widgets import two_state_template
|
||||
from common.utils import pretty_size
|
||||
from converter.literals import (
|
||||
DEFAULT_PAGE_NUMBER, DEFAULT_ROTATION, DEFAULT_ZOOM_LEVEL
|
||||
)
|
||||
@@ -36,8 +35,8 @@ from .events import (
|
||||
)
|
||||
from .forms import (
|
||||
DocumentDownloadForm, DocumentForm, DocumentPageForm, DocumentPreviewForm,
|
||||
DocumentPropertiesForm, DocumentTypeFilenameForm,
|
||||
DocumentTypeFilenameForm_create, DocumentTypeSelectForm, PrintForm
|
||||
DocumentPropertiesForm, DocumentTypeSelectForm,
|
||||
DocumentTypeFilenameForm_create, PrintForm
|
||||
)
|
||||
from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT
|
||||
from .models import (
|
||||
|
||||
@@ -8,7 +8,7 @@ from rest_api.filters import MayanObjectPermissionsFilter
|
||||
from .classes import SearchModel
|
||||
from .filters import RecentSearchUserFilter
|
||||
from .models import RecentSearch
|
||||
from .serializers import RecentSearchSerializer, SearchSerializer
|
||||
from .serializers import RecentSearchSerializer
|
||||
|
||||
|
||||
class APIRecentSearchListView(generics.ListAPIView):
|
||||
|
||||
@@ -15,7 +15,3 @@ class RecentSearchSerializer(serializers.HyperlinkedModelSerializer):
|
||||
fields = ('datetime_created', 'hits', 'query', 'url', 'user')
|
||||
model = RecentSearch
|
||||
read_only_fields = ('datetime_created', 'hits', 'query', 'user')
|
||||
|
||||
|
||||
class SearchSerializer(serializers.Serializer):
|
||||
results = serializers.CharField()
|
||||
|
||||
@@ -6,8 +6,6 @@ import urlparse
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.generics import SimpleView, SingleObjectListView
|
||||
|
||||
@@ -20,7 +20,8 @@ class EventsApp(MayanAppConfig):
|
||||
|
||||
SourceColumn(source=Action, label=_('Timestamp'), attribute='timestamp')
|
||||
SourceColumn(source=Action, label=_('Actor'), attribute='actor')
|
||||
SourceColumn(source=Action, label=_('Verb'),
|
||||
SourceColumn(
|
||||
source=Action, label=_('Verb'),
|
||||
func=lambda context: event_type_link(context['object'])
|
||||
)
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.shortcuts import render_to_response
|
||||
from django.template import RequestContext
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.generics import SingleObjectListView
|
||||
from permissions import Permission
|
||||
|
||||
from .classes import PropertyNamespace
|
||||
from .permissions import permission_installation_details
|
||||
@@ -37,4 +34,3 @@ class NamespaceDetailView(SingleObjectListView):
|
||||
|
||||
def get_queryset(self):
|
||||
return self.get_namespace().get_properties()
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ from common.generics import (
|
||||
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
|
||||
SingleObjectListView
|
||||
)
|
||||
from common.widgets import two_state_template
|
||||
from documents.models import Document, DocumentType
|
||||
from documents.permissions import permission_document_view
|
||||
from documents.views import DocumentListView
|
||||
|
||||
@@ -11,7 +11,7 @@ from fuse import FUSE, FuseOSError, Operations
|
||||
from django.core import management
|
||||
from django.core.cache import caches
|
||||
from django.core.exceptions import MultipleObjectsReturned
|
||||
from django.db.models import Count, Max
|
||||
from django.db.models import Count
|
||||
|
||||
from document_indexing.models import Index, IndexInstanceNode
|
||||
from documents.models import Document
|
||||
|
||||
@@ -32,8 +32,14 @@ class UserManagementApp(MayanAppConfig):
|
||||
|
||||
APIEndPoint(app=self, version_string='1')
|
||||
|
||||
MetadataLookup(description=_('All the groups.'), name='group', value=Group.objects.all())
|
||||
MetadataLookup(description=_('All the users.'), name='users', value=get_user_model().objects.all())
|
||||
MetadataLookup(
|
||||
description=_('All the groups.'), name='group',
|
||||
value=Group.objects.all()
|
||||
)
|
||||
MetadataLookup(
|
||||
description=_('All the users.'), name='users',
|
||||
value=get_user_model().objects.all()
|
||||
)
|
||||
|
||||
SourceColumn(
|
||||
source=Group, label=_('Members'), attribute='user_set.count'
|
||||
@@ -47,11 +53,15 @@ class UserManagementApp(MayanAppConfig):
|
||||
)
|
||||
SourceColumn(
|
||||
source=User, label=_('Active'),
|
||||
func=lambda context: two_state_template(context['object'].is_active)
|
||||
func=lambda context: two_state_template(
|
||||
context['object'].is_active
|
||||
)
|
||||
)
|
||||
SourceColumn(
|
||||
source=User, label=_('Has usable password?'),
|
||||
func=lambda context: two_state_template(context['object'].has_usable_password())
|
||||
func=lambda context: two_state_template(
|
||||
context['object'].has_usable_password()
|
||||
)
|
||||
)
|
||||
|
||||
menu_multi_item.bind_links(
|
||||
|
||||
@@ -14,7 +14,6 @@ from common.views import (
|
||||
AssignRemoveView, SingleObjectCreateView, SingleObjectEditView,
|
||||
SingleObjectListView
|
||||
)
|
||||
from common.widgets import two_state_template
|
||||
from permissions import Permission
|
||||
|
||||
from .forms import PasswordForm, UserForm
|
||||
@@ -47,7 +46,10 @@ def user_edit(request, user_id):
|
||||
if user.is_superuser or user.is_staff:
|
||||
messages.error(
|
||||
request,
|
||||
_('Super user and staff user editing is not allowed, use the admin interface for these cases.')
|
||||
_(
|
||||
'Super user and staff user editing is not allowed, use the '
|
||||
'admin interface for these cases.'
|
||||
)
|
||||
)
|
||||
return HttpResponseRedirect(
|
||||
request.META.get(
|
||||
@@ -106,7 +108,9 @@ def user_delete(request, user_id=None, user_id_list=None):
|
||||
post_action_redirect = reverse('user_management:user_list')
|
||||
elif user_id_list:
|
||||
users = [
|
||||
get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',')
|
||||
get_object_or_404(
|
||||
User, pk=user_id
|
||||
) for user_id in user_id_list.split(',')
|
||||
]
|
||||
else:
|
||||
messages.error(request, _('Must provide at least one user.'))
|
||||
@@ -123,14 +127,24 @@ def user_delete(request, user_id=None, user_id_list=None):
|
||||
for user in users:
|
||||
try:
|
||||
if user.is_superuser or user.is_staff:
|
||||
messages.error(request, _('Super user and staff user deleting is not allowed, use the admin interface for these cases.'))
|
||||
messages.error(
|
||||
request,
|
||||
_(
|
||||
'Super user and staff user deleting is not '
|
||||
'allowed, use the admin interface for these cases.'
|
||||
)
|
||||
)
|
||||
else:
|
||||
user.delete()
|
||||
messages.success(request, _('User "%s" deleted successfully.') % user)
|
||||
messages.success(
|
||||
request, _('User "%s" deleted successfully.') % user
|
||||
)
|
||||
except Exception as exception:
|
||||
messages.error(request, _('Error deleting user "%(user)s": %(error)s') % {
|
||||
'user': user, 'error': exception
|
||||
})
|
||||
messages.error(
|
||||
request, _('Error deleting user "%(user)s": %(error)s') % {
|
||||
'user': user, 'error': exception
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponseRedirect(next)
|
||||
|
||||
@@ -145,8 +159,10 @@ def user_delete(request, user_id=None, user_id_list=None):
|
||||
elif len(users) > 1:
|
||||
context['title'] = _('Delete the users: %s?') % ', '.join([unicode(d) for d in users])
|
||||
|
||||
return render_to_response('appearance/generic_confirm.html', context,
|
||||
context_instance=RequestContext(request))
|
||||
return render_to_response(
|
||||
'appearance/generic_confirm.html', context,
|
||||
context_instance=RequestContext(request)
|
||||
)
|
||||
|
||||
|
||||
def user_multiple_delete(request):
|
||||
@@ -166,7 +182,11 @@ def user_set_password(request, user_id=None, user_id_list=None):
|
||||
users = [get_object_or_404(User, pk=user_id) for user_id in user_id_list.split(',')]
|
||||
else:
|
||||
messages.error(request, _('Must provide at least one user.'))
|
||||
return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))
|
||||
return HttpResponseRedirect(
|
||||
request.META.get(
|
||||
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
|
||||
)
|
||||
)
|
||||
|
||||
next = request.POST.get('next', request.GET.get('next', post_action_redirect if post_action_redirect else request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
|
||||
|
||||
@@ -181,15 +201,30 @@ def user_set_password(request, user_id=None, user_id_list=None):
|
||||
for user in users:
|
||||
try:
|
||||
if user.is_superuser or user.is_staff:
|
||||
messages.error(request, _('Super user and staff user password reseting is not allowed, use the admin interface for these cases.'))
|
||||
messages.error(
|
||||
request,
|
||||
_(
|
||||
'Super user and staff user password '
|
||||
'reseting is not allowed, use the admin '
|
||||
'interface for these cases.'
|
||||
)
|
||||
)
|
||||
else:
|
||||
user.set_password(password_1)
|
||||
user.save()
|
||||
messages.success(request, _('Successfull password reset for user: %s.') % user)
|
||||
messages.success(
|
||||
request, _(
|
||||
'Successfull password reset for user: %s.'
|
||||
) % user
|
||||
)
|
||||
except Exception as exception:
|
||||
messages.error(request, _('Error reseting password for user "%(user)s": %(error)s') % {
|
||||
'user': user, 'error': exception
|
||||
})
|
||||
messages.error(
|
||||
request, _(
|
||||
'Error reseting password for user "%(user)s": %(error)s'
|
||||
) % {
|
||||
'user': user, 'error': exception
|
||||
}
|
||||
)
|
||||
|
||||
return HttpResponseRedirect(next)
|
||||
else:
|
||||
@@ -243,10 +278,14 @@ class UserGroupsView(AssignRemoveView):
|
||||
return get_object_or_404(User, pk=self.kwargs['pk'])
|
||||
|
||||
def left_list(self):
|
||||
return AssignRemoveView.generate_choices(get_user_non_groups(self.get_object()))
|
||||
return AssignRemoveView.generate_choices(
|
||||
get_user_non_groups(self.get_object())
|
||||
)
|
||||
|
||||
def right_list(self):
|
||||
return AssignRemoveView.generate_choices(get_user_groups(self.get_object()))
|
||||
return AssignRemoveView.generate_choices(
|
||||
get_user_groups(self.get_object())
|
||||
)
|
||||
|
||||
def remove(self, item):
|
||||
item.user_set.remove(self.get_object())
|
||||
@@ -297,7 +336,9 @@ def group_delete(request, group_id=None, group_id_list=None):
|
||||
groups = [get_object_or_404(Group, pk=group_id)]
|
||||
post_action_redirect = reverse('user_management:group_list')
|
||||
elif group_id_list:
|
||||
groups = [get_object_or_404(Group, pk=group_id) for group_id in group_id_list.split(',')]
|
||||
groups = [
|
||||
get_object_or_404(Group, pk=group_id) for group_id in group_id_list.split(',')
|
||||
]
|
||||
else:
|
||||
messages.error(request, _('Must provide at least one group.'))
|
||||
return HttpResponseRedirect(request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))
|
||||
@@ -359,10 +400,16 @@ class GroupMembersView(AssignRemoveView):
|
||||
return get_object_or_404(Group, pk=self.kwargs['pk'])
|
||||
|
||||
def left_list(self):
|
||||
return AssignRemoveView.generate_choices(User.objects.exclude(groups=self.get_object()).exclude(is_staff=True).exclude(is_superuser=True))
|
||||
return AssignRemoveView.generate_choices(
|
||||
User.objects.exclude(
|
||||
groups=self.get_object()
|
||||
).exclude(is_staff=True).exclude(is_superuser=True)
|
||||
)
|
||||
|
||||
def right_list(self):
|
||||
return AssignRemoveView.generate_choices(self.get_object().user_set.all())
|
||||
return AssignRemoveView.generate_choices(
|
||||
self.get_object().user_set.all()
|
||||
)
|
||||
|
||||
def remove(self, item):
|
||||
self.get_object().user_set.remove(item)
|
||||
|
||||
Reference in New Issue
Block a user