summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2018-11-29 19:34:31 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2018-11-29 19:34:31 +0100
commitafd7fb9c2be01a44a45f582eebdf02632a10be99 (patch)
tree05cdd1da4246ddb4e3e8b69c9a968f3e0d14d7b9
parentc0c093276dec2a34c5702711e3c3147b98ca4df8 (diff)
downloadIshtar-afd7fb9c2be01a44a45f582eebdf02632a10be99.tar.bz2
Ishtar-afd7fb9c2be01a44a45f582eebdf02632a10be99.zip
Basket: manage basket share (ro and edit) - manage alt query own
-rw-r--r--archaeological_finds/forms.py72
-rw-r--r--archaeological_finds/migrations/0042_auto_20181129_1755.py30
-rw-r--r--archaeological_finds/models_finds.py24
-rw-r--r--archaeological_finds/templates/ishtar/sheet_findbasket.html3
-rw-r--r--archaeological_finds/urls.py2
-rw-r--r--archaeological_finds/views.py17
-rw-r--r--archaeological_finds/wizards.py1
-rw-r--r--ishtar_common/migrations/0077_auto_20181129_1755.py20
-rw-r--r--ishtar_common/models.py17
-rw-r--r--ishtar_common/templates/ishtar/blocks/window_field_flex_multiple_full.html8
-rw-r--r--ishtar_common/templates/ishtar/form.html3
-rw-r--r--ishtar_common/templatetags/window_field.py8
-rw-r--r--ishtar_common/urls.py2
-rw-r--r--ishtar_common/views.py23
-rw-r--r--ishtar_common/views_item.py60
-rw-r--r--ishtar_common/wizards.py18
-rw-r--r--scss/custom.scss1
17 files changed, 256 insertions, 53 deletions
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py
index 90e1390bf..811e71a60 100644
--- a/archaeological_finds/forms.py
+++ b/archaeological_finds/forms.py
@@ -57,7 +57,7 @@ from ishtar_common.forms import CustomForm, CustomFormSearch, FormSet, \
PkWizardSearch
from ishtar_common.forms_common import get_town_field
from ishtar_common.models import valid_id, valid_ids, get_current_profile, \
- SpatialReferenceSystem, Area, OperationType
+ SpatialReferenceSystem, Area, OperationType, IshtarUser
from ishtar_common.utils import convert_coordinates_to_point
__all__ = [
@@ -74,6 +74,7 @@ __all__ = [
'DashboardTreatmentForm', 'DashboardTreatmentFileForm',
'RecordFormSelection', 'FindForm', 'SimpleFindForm', 'DateForm',
'DatingFormSet', 'PreservationForm', 'FindBasketFormSelection',
+ 'FindBasketForWriteFormSelection',
'FindBasketForm', 'FindSelect', 'FindFormSelection',
'FindFormSelectionWarehouseModule', 'MultipleFindFormSelection',
'MultipleFindFormSelectionWarehouseModule', 'FindMultipleFormSelection',
@@ -883,7 +884,8 @@ class FindSelect(HistorySelect):
if self.current_user:
self.fields['basket'].choices += [
(b.pk, b.label) for b in models.FindBasket.objects.filter(
- user=self.current_user).all()]
+ models.FindBasket.get_query_owns(self.current_user)
+ ).all()]
def get_input_ids(self):
ids = super(FindSelect, self).get_input_ids()
@@ -1169,19 +1171,57 @@ class FindBasketFormSelection(CustomFormSearch):
validators=[valid_id(models.FindBasket)])
+class FindBasketForWriteFormSelection(CustomFormSearch):
+ SEARCH_AND_SELECT = True
+ form_label = _("Basket search")
+ associated_models = {'pk': models.FindBasket}
+ currents = {'pk': models.FindBasket}
+
+ pk = forms.IntegerField(
+ label="", required=False,
+ widget=widgets.DataTable(
+ reverse_lazy('get-findbasket-write'),
+ FindBasketSelect, models.FindBasket,
+ ),
+ validators=[valid_id(models.FindBasket)])
+
+
class FindBasketForm(IshtarForm):
form_label = _(u"Find basket")
+ associated_models = {"shared_with": IshtarUser,
+ "shared_write_with": IshtarUser}
label = forms.CharField(
label=_(u"Label"),
validators=[validators.MaxLengthValidator(1000)])
comment = forms.CharField(label=_(u"Comment"),
widget=forms.Textarea, required=False)
+ shared_with = widgets.Select2MultipleField(
+ model=IshtarUser, remote=True,
+ label=_(u"Shared (read) with"),
+ required=False, long_widget=True
+ )
+ shared_write_with = widgets.Select2MultipleField(
+ model=IshtarUser, remote=True,
+ label=_(u"Shared (read/edit) with"),
+ required=False, long_widget=True
+ )
-class NewFindBasketForm(forms.ModelForm):
+class NewFindBasketForm(forms.ModelForm, IshtarForm):
+ shared_with = widgets.Select2MultipleField(
+ model=IshtarUser, remote=True,
+ label=_(u"Shared (read) with"),
+ required=False, long_widget=True
+ )
+ shared_write_with = widgets.Select2MultipleField(
+ model=IshtarUser, remote=True,
+ label=_(u"Shared (read/edit) with"),
+ required=False, long_widget=True
+ )
+
class Meta:
model = models.FindBasket
- fields = ('label', 'comment')
+ fields = ('label', 'comment', 'shared_with', 'shared_write_with')
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
@@ -1217,14 +1257,26 @@ class SelectFindBasketForm(IshtarForm):
super(SelectFindBasketForm, self).__init__(*args, **kwargs)
if not self.user:
return
- self.fields['basket'].choices = [('', '--')] + [
- (b.pk, unicode(b))
+ self.fields['basket'].choices = self.get_basket_choices()
+
+ def get_basket_choices(self):
+ return [('', u'--')] + [
+ (str(b.pk), unicode(b))
for b in models.FindBasket.objects.filter(
- Q(user=self.user) | Q(shared_with=self.user)
- )]
+ Q(user=self.user) | Q(shared_write_with=self.user)
+ )
+ ]
class DeleteFindBasketForm(SelectFindBasketForm):
+ def get_basket_choices(self):
+ return [('', u'--')] + [
+ (str(b.pk), unicode(b))
+ for b in models.FindBasket.objects.filter(
+ Q(user=self.user)
+ )
+ ]
+
def save(self):
try:
models.FindBasket.objects.get(pk=self.cleaned_data['basket'],
@@ -1242,8 +1294,8 @@ class FindBasketAddItemForm(forms.Form):
def save(self, user):
try:
basket = models.FindBasket.objects.filter(
- Q(user=user) | Q(shared_with=user)
- ).get(pk=self.cleaned_data['basket_id'])
+ Q(user=user) | Q(shared_with=user) | Q(shared_write_with=user)
+ ).distinct().get(pk=self.cleaned_data['basket_id'])
item = models.Find.objects.get(
pk=self.cleaned_data['item_id'])
except models.FindBasket.DoesNotExist or\
diff --git a/archaeological_finds/migrations/0042_auto_20181129_1755.py b/archaeological_finds/migrations/0042_auto_20181129_1755.py
new file mode 100644
index 000000000..42d732cf2
--- /dev/null
+++ b/archaeological_finds/migrations/0042_auto_20181129_1755.py
@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2018-11-29 17:55
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0077_auto_20181129_1755'),
+ ('archaeological_finds', '0041_auto_20181121_1225'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='treatmentfile',
+ options={'ordering': ('cached_label',), 'permissions': (('view_treatmentfile', 'Can view all Treatment requests'), ('view_own_treatmentfile', 'Can view own Treatment request'), ('add_own_treatmentfile', 'Can add own Treatment request'), ('change_own_treatmentfile', 'Can change own Treatment request'), ('delete_own_treatmentfile', 'Can delete own Treatment request')), 'verbose_name': 'Treatment request', 'verbose_name_plural': 'Treatment requests'},
+ ),
+ migrations.AddField(
+ model_name='findbasket',
+ name='shared_write_with',
+ field=models.ManyToManyField(blank=True, related_name='shared_write_findbaskets', to='ishtar_common.IshtarUser', verbose_name='Shared (read/edit) with'),
+ ),
+ migrations.AlterField(
+ model_name='findbasket',
+ name='shared_with',
+ field=models.ManyToManyField(blank=True, related_name='shared_findbaskets', to='ishtar_common.IshtarUser', verbose_name='Shared (read) with'),
+ ),
+ ]
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 9baced4e0..0c9770186 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -591,6 +591,11 @@ class FindBasket(Basket, OwnPerms):
@classmethod
def get_query_owns(cls, ishtaruser):
+ return Q(user=ishtaruser) | Q(shared_with=ishtaruser) | Q(
+ shared_write_with=ishtaruser)
+
+ @classmethod
+ def get_write_query_owns(cls, ishtaruser):
return Q(user=ishtaruser)
def get_extra_actions(self, request):
@@ -599,13 +604,18 @@ class FindBasket(Basket, OwnPerms):
"""
# url, base_text, icon, extra_text, extra css class, is a quick action
- # no particular rights: if you can view an itm you can add it to your
- # own basket
- actions = [
- (reverse("select_itemsinbasket", args=[self.pk]),
- _(u"Manage basket"),
- "fa fa-shopping-basket", "", "", False),
- ]
+ if not request.user or not request.user.ishtaruser:
+ return []
+
+ ishtaruser = request.user.ishtaruser
+ actions = []
+ if self.user == ishtaruser or ishtaruser.pk in [
+ user.pk for user in self.shared_write_with.all()]:
+ actions = [
+ (reverse("select_itemsinbasket", args=[self.pk]),
+ _(u"Manage basket"),
+ "fa fa-shopping-basket", "", "", False),
+ ]
return actions
diff --git a/archaeological_finds/templates/ishtar/sheet_findbasket.html b/archaeological_finds/templates/ishtar/sheet_findbasket.html
index 3c3ca1d3f..4a101d8f2 100644
--- a/archaeological_finds/templates/ishtar/sheet_findbasket.html
+++ b/archaeological_finds/templates/ishtar/sheet_findbasket.html
@@ -12,8 +12,9 @@
<div class='row'>
{% field_flex "Label" item.label %}
{% field_flex_detail "Owned by" item.user.person %}
- {% field_flex_multiple "Shared_with" item.shared_with %}
{% field_flex "Comment" item.comment %}
+ {% field_flex_multiple_full "Shared (read) with" item.shared_with %}
+ {% field_flex_multiple_full "Shared (read/edit) with" item.shared_write_with %}
</div>
<h3>{% trans "Content" %}</h3>
diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py
index 6e9f59b8c..0ef3bac89 100644
--- a/archaeological_finds/urls.py
+++ b/archaeological_finds/urls.py
@@ -45,6 +45,8 @@ urlpatterns = [
views.find_modify, name='find_modify'),
url(r'get-findbasket/$', views.get_find_basket,
name='get-findbasket'),
+ url(r'get-findbasket-write/$', views.get_find_basket_for_write,
+ name='get-findbasket-write'),
url(r'find_basket_search/(?P<step>.+)?$',
check_rights(['view_find', 'view_own_find'])(
views.basket_search_wizard), name='find_basket_search'),
diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py
index 29f0f75af..125567044 100644
--- a/archaeological_finds/views.py
+++ b/archaeological_finds/views.py
@@ -109,12 +109,19 @@ show_find = show_item(models.Find, 'find')
display_find = display_item(models.Find)
revert_find = revert_item(models.Find)
-show_findbasket = show_item(models.FindBasket, 'findbasket')
+show_findbasket = show_item(models.FindBasket, 'findbasket',
+ model_for_perms=models.Find)
display_findbasket = display_item(models.FindBasket,
show_url='show-find/basket-')
get_find_basket = get_item(
models.FindBasket, 'get_findbasket', 'findbasket',
+ model_for_perms=models.Find
+)
+
+get_find_basket_for_write = get_item(
+ models.FindBasket, 'get_findbasket', 'findbasket',
+ model_for_perms=models.Find, alt_query_own='get_write_query_owns'
)
basket_search_wizard = FindBasketSearch.as_view(
@@ -125,10 +132,10 @@ basket_search_wizard = FindBasketSearch.as_view(
basket_modify_wizard = FindBasketEditWizard.as_view(
[
- ('selec-find_basket_modification', FindBasketFormSelection),
+ ('selec-find_basket_modification', FindBasketForWriteFormSelection),
('basket-find_basket_modification', FindBasketForm),
('final-find_basket_modification', FinalForm)
- ],
+ ],
label=_(u"Basket modify"),
url_name='find_basket_modification',
)
@@ -290,8 +297,8 @@ class OwnBasket(object):
def get_basket(self, user, pk):
try:
return models.FindBasket.objects.filter(
- Q(user=user) | Q(shared_with=user)
- ).get(pk=pk)
+ Q(user=user) | Q(shared_with=user) | Q(shared_write_with=user)
+ ).distinct().get(pk=pk)
except models.FindBasket.DoesNotExist:
raise PermissionDenied
diff --git a/archaeological_finds/wizards.py b/archaeological_finds/wizards.py
index 43f48ab59..6d4fd2d95 100644
--- a/archaeological_finds/wizards.py
+++ b/archaeological_finds/wizards.py
@@ -500,3 +500,4 @@ class FindBasketWizard(Wizard):
class FindBasketEditWizard(FindBasketWizard):
edit = True
+ alt_is_own_method = 'get_write_query_owns'
diff --git a/ishtar_common/migrations/0077_auto_20181129_1755.py b/ishtar_common/migrations/0077_auto_20181129_1755.py
new file mode 100644
index 000000000..bd9003946
--- /dev/null
+++ b/ishtar_common/migrations/0077_auto_20181129_1755.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.10 on 2018-11-29 17:55
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('ishtar_common', '0076_migrate_treatmentfile_permissions'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='importertype',
+ name='is_template',
+ field=models.BooleanField(default=False, verbose_name='Can be exported'),
+ ),
+ ]
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 1aa94836f..1a0d80ac3 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -254,7 +254,7 @@ class OwnPerms(object):
action_own_name, request.session)
and self.is_own(request.user.ishtaruser))
- def is_own(self, user):
+ def is_own(self, user, alt_query_own=None):
"""
Check if the current object is owned by the user
"""
@@ -264,7 +264,10 @@ class OwnPerms(object):
ishtaruser = user.ishtaruser
else:
return False
- query = self.get_query_owns(ishtaruser)
+ if not alt_query_own:
+ query = self.get_query_owns(ishtaruser)
+ else:
+ query = getattr(self, alt_query_own)(ishtaruser)
if not query:
return False
query &= Q(pk=self.pk)
@@ -3293,6 +3296,7 @@ post_save.connect(post_save_userprofile, sender=UserProfile)
class IshtarUser(FullSearch):
+ SLUG = "ishtaruser"
TABLE_COLS = ('username', 'person__name', 'person__surname',
'person__email', 'person__person_types_list',
'person__attached_to__name')
@@ -3441,9 +3445,13 @@ class Basket(FullSearch):
verbose_name=_(u"Owner"))
available = models.BooleanField(_(u"Available"), default=True)
shared_with = models.ManyToManyField(
- IshtarUser, verbose_name=_(u"Shared with"), blank=True,
+ IshtarUser, verbose_name=_(u"Shared (read) with"), blank=True,
related_name='shared_%(class)ss'
)
+ shared_write_with = models.ManyToManyField(
+ IshtarUser, verbose_name=_(u"Shared (read/edit) with"), blank=True,
+ related_name='shared_write_%(class)ss'
+ )
TABLE_COLS = ['label', 'user']
@@ -3462,7 +3470,8 @@ class Basket(FullSearch):
if not request.user or not getattr(request.user, 'ishtaruser', None):
return Q(pk=None)
ishtaruser = request.user.ishtaruser
- return Q(user=ishtaruser) | Q(shared_with=ishtaruser)
+ return Q(user=ishtaruser) | Q(shared_with=ishtaruser) | Q(
+ shared_write_with=ishtaruser)
@property
def cached_label(self):
diff --git a/ishtar_common/templates/ishtar/blocks/window_field_flex_multiple_full.html b/ishtar_common/templates/ishtar/blocks/window_field_flex_multiple_full.html
new file mode 100644
index 000000000..b70c1d2fc
--- /dev/null
+++ b/ishtar_common/templates/ishtar/blocks/window_field_flex_multiple_full.html
@@ -0,0 +1,8 @@
+{% load i18n %}{% if data.count %}
+ <dl class="col-12 row">
+ <dt class="col-12">{% trans caption %}</dt>
+ <dd class="col-12">{% for d in data.distinct.all %}
+ {% if forloop.counter0 %} ; {% endif %}{{ d }}
+ {% endfor %}</dd>
+ </dl>
+{% endif %}
diff --git a/ishtar_common/templates/ishtar/form.html b/ishtar_common/templates/ishtar/form.html
index b99d504a0..bcd69959e 100644
--- a/ishtar_common/templates/ishtar/form.html
+++ b/ishtar_common/templates/ishtar/form.html
@@ -1,5 +1,8 @@
{% extends "base.html" %}
{% load i18n inline_formset table_form %}
+{% block extra_head %}
+{{form.media}}
+{% endblock %}
{% block pre_container %}
<form enctype="multipart/form-data" action="." method="post"{% if confirm %}
onsubmit='return confirm("{{confirm}}");'{% endif %}>{% csrf_token %}
diff --git a/ishtar_common/templatetags/window_field.py b/ishtar_common/templatetags/window_field.py
index 46329a3fa..a5bae3b72 100644
--- a/ishtar_common/templatetags/window_field.py
+++ b/ishtar_common/templatetags/window_field.py
@@ -108,6 +108,14 @@ def field_flex_multiple(caption, data, small=False):
return field_multiple(caption, data, size=size)
+@register.inclusion_tag('ishtar/blocks/window_field_flex_multiple_full.html')
+def field_flex_multiple_full(caption, data, small=False):
+ size = None
+ if small:
+ size = 2
+ return field_multiple(caption, data, size=size)
+
+
@register.inclusion_tag('ishtar/blocks/window_field_detail.html')
def field_detail(caption, item, li=False, size=None):
return {'caption': caption, 'item': item, 'link': link_to_window(item),
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index 8d06b6862..aea419d08 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -174,6 +174,8 @@ urlpatterns += [
views.new_person_noorga, name='new-person-noorga'),
url(r'autocomplete-user/$',
views.autocomplete_user, name='autocomplete-user'),
+ url(r'autocomplete-ishtaruser/$',
+ views.autocomplete_ishtaruser, name='autocomplete-ishtaruser'),
url(r'autocomplete-person(?:/([0-9_]+))?(?:/([0-9_]*))?/(user)?$',
views.autocomplete_person, name='autocomplete-person'),
url(r'autocomplete-person-permissive(?:/([0-9_]+))?(?:/([0-9_]*))?'
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 3d64535d4..bc9c9432a 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -527,6 +527,29 @@ def autocomplete_user(request):
return HttpResponse(data, content_type='text/plain')
+def autocomplete_ishtaruser(request):
+ if not request.user.has_perm('ishtar_common.view_person', models.Person):
+ return HttpResponse('[]', content_type='text/plain')
+ q = request.GET.get('term')
+ limit = request.GET.get('limit', 20)
+ try:
+ limit = int(limit)
+ except ValueError:
+ return HttpResponseBadRequest()
+ query = Q()
+ for q in q.split(' '):
+ qu = (Q(person__name__icontains=q) |
+ Q(person__surname__icontains=q) |
+ Q(person__raw_name__icontains=q))
+ query = query & qu
+ users = models.IshtarUser.objects.filter(query)[:limit]
+ data = json.dumps([
+ {'id': user.pk,
+ 'value': unicode(user)}
+ for user in users])
+ return HttpResponse(data, content_type='text/plain')
+
+
def autocomplete_person(request, person_types=None, attached_to=None,
is_ishtar_user=None, permissive=False):
all_items = request.user.has_perm('ishtar_common.view_person',
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 71890fa6e..f34b2357f 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -133,22 +133,25 @@ def display_item(model, extra_dct=None, show_url=None):
return func
-def show_item(model, name, extra_dct=None):
+def show_item(model, name, extra_dct=None, model_for_perms=None):
def func(request, pk, **dct):
- allowed, own = check_model_access_control(request, model)
+ check_model = model
+ if model_for_perms:
+ check_model = model_for_perms
+ allowed, own = check_model_access_control(request, check_model)
if not allowed:
return HttpResponse('', content_type="application/xhtml")
q = model.objects
if own:
if not hasattr(request.user, 'ishtaruser'):
- return HttpResponse('NOK')
+ return HttpResponse('')
query_own = model.get_query_owns(request.user.ishtaruser)
if query_own:
q = q.filter(query_own).distinct()
try:
item = q.get(pk=pk)
except ObjectDoesNotExist:
- return HttpResponse('NOK')
+ return HttpResponse('')
doc_type = 'type' in dct and dct.pop('type')
url_name = u"/".join(reverse('show-' + name, args=['0', '']
).split('/')[:-2]) + u"/"
@@ -879,11 +882,13 @@ DEFAULT_ROW_NUMBER = 10
EXCLUDED_FIELDS = ['length']
-def get_item(model, func_name, default_name, extra_request_keys=[],
- base_request=None, bool_fields=[], reversed_bool_fields=[],
- dated_fields=[], associated_models=[], relative_session_names=[],
- specific_perms=[], own_table_cols=None, relation_types_prefix={},
- do_not_deduplicate=False):
+def get_item(model, func_name, default_name, extra_request_keys=None,
+ base_request=None, bool_fields=None, reversed_bool_fields=None,
+ dated_fields=None, associated_models=None,
+ relative_session_names=None, specific_perms=None,
+ own_table_cols=None, relation_types_prefix=None,
+ do_not_deduplicate=False, model_for_perms=None,
+ alt_query_own=None):
"""
Generic treatment of tables
@@ -903,6 +908,8 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
:param do_not_deduplicate: duplication of id can occurs on large queryset a
mecanism of deduplication is used. But duplicate ids can be normal (for
instance for record_relations view).
+ :param model_for_perms: use another model to check permission
+ :param alt_query_own: name of alternate method to get query_own
:return:
"""
def func(request, data_type='json', full=False, force_own=False,
@@ -914,10 +921,15 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
if 'type' in dct:
data_type = dct.pop('type')
if not data_type:
- EMPTY = '[]'
data_type = 'json'
+ if data_type == "json":
+ EMPTY = '[]'
- allowed, own = check_model_access_control(request, model,
+ model_to_check = model
+ if model_for_perms:
+ model_to_check = model_for_perms
+
+ allowed, own = check_model_access_control(request, model_to_check,
available_perms)
if not allowed:
return HttpResponse(EMPTY, content_type='text/plain')
@@ -933,13 +945,16 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
q = models.IshtarUser.objects.filter(user_ptr=request.user)
if not q.count():
return HttpResponse(EMPTY, content_type='text/plain')
- query_own = model.get_query_owns(q.all()[0])
+ if alt_query_own:
+ query_own = getattr(model, alt_query_own)(q.all()[0])
+ else:
+ query_own = model.get_query_owns(q.all()[0])
# get defaults from model
if not extra_request_keys and hasattr(model, 'EXTRA_REQUEST_KEYS'):
my_extra_request_keys = copy(model.EXTRA_REQUEST_KEYS)
else:
- my_extra_request_keys = copy(extra_request_keys)
+ my_extra_request_keys = copy(extra_request_keys or [])
if base_request is None and hasattr(model, 'BASE_REQUEST'):
if callable(model.BASE_REQUEST):
my_base_request = model.BASE_REQUEST(request)
@@ -952,32 +967,35 @@ def get_item(model, func_name, default_name, extra_request_keys=[],
if not bool_fields and hasattr(model, 'BOOL_FIELDS'):
my_bool_fields = model.BOOL_FIELDS[:]
else:
- my_bool_fields = bool_fields[:]
+ my_bool_fields = bool_fields[:] if bool_fields else []
if not reversed_bool_fields and hasattr(model, 'REVERSED_BOOL_FIELDS'):
my_reversed_bool_fields = model.REVERSED_BOOL_FIELDS[:]
else:
- my_reversed_bool_fields = reversed_bool_fields[:]
+ my_reversed_bool_fields = reversed_bool_fields[:] \
+ if reversed_bool_fields else []
if not dated_fields and hasattr(model, 'DATED_FIELDS'):
my_dated_fields = model.DATED_FIELDS[:]
else:
- my_dated_fields = dated_fields[:]
+ my_dated_fields = dated_fields[:] if dated_fields else []
if not associated_models and hasattr(model, 'ASSOCIATED_MODELS'):
my_associated_models = model.ASSOCIATED_MODELS[:]
else:
- my_associated_models = associated_models[:]
+ my_associated_models = associated_models[:] \
+ if associated_models else []
if not relative_session_names and hasattr(model,
'RELATIVE_SESSION_NAMES'):
my_relative_session_names = model.RELATIVE_SESSION_NAMES[:]
else:
- my_relative_session_names = relative_session_names[:]
+ my_relative_session_names = relative_session_names[:] \
+ if relative_session_names else []
if not relation_types_prefix and hasattr(model,
'RELATION_TYPES_PREFIX'):
my_relation_types_prefix = copy(model.RELATION_TYPES_PREFIX)
else:
- my_relation_types_prefix = copy(relation_types_prefix)
+ my_relation_types_prefix = copy(relation_types_prefix) \
+ if relation_types_prefix else {}
- fields = [model._meta.get_field(k)
- for k in get_all_field_names(model)]
+ fields = [model._meta.get_field(k) for k in get_all_field_names(model)]
request_keys = dict([
(field.name,
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index b3fc4b55a..19eb312e1 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -23,6 +23,7 @@ import os
# from functools import wraps
from django.conf import settings
+from django.contrib import messages
from formtools.wizard.views import NamedUrlWizardView, normalize_name, \
get_storage, StepsHelper
@@ -115,6 +116,7 @@ class Wizard(IshtarWizard):
)
main_item_select_keys = ('selec-',)
formset_pop_deleted = True
+ alt_is_own_method = None # alternate method name for "is_own" check
saved_args = {} # argument to pass on object save
@@ -164,11 +166,17 @@ class Wizard(IshtarWizard):
ishtaruser = request.user.ishtaruser \
if hasattr(request.user, 'ishtaruser') else None
- # not the fisrt step and current object is not owned
- if self.steps and self.steps.first != step and\
- current_object and not current_object.is_own(ishtaruser):
- self.session_reset(request, self.url_name)
- return HttpResponseRedirect('/')
+ # not the first step and current object is not owned
+ if self.steps and self.steps.first != step and current_object:
+ is_own = current_object.is_own(
+ ishtaruser, alt_query_own=self.alt_is_own_method)
+ if not is_own:
+ messages.add_message(
+ request, messages.WARNING,
+ _(u"Permission error: you cannot do this action.")
+ )
+ self.session_reset(request, self.url_name)
+ return HttpResponseRedirect('/')
# extra filter on forms
self.filter_owns_items = True
else:
diff --git a/scss/custom.scss b/scss/custom.scss
index 09074de0b..56dbffab6 100644
--- a/scss/custom.scss
+++ b/scss/custom.scss
@@ -610,6 +610,7 @@ ul.compact{
margin: 0;
display: block;
outline: none;
+ font-size: 1.1em;
}
.ui-helper-hidden {