summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-10 18:02:50 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2019-09-10 18:02:50 +0200
commit0c185f1abbe9abe0d977e1b7d1d3f0440b8d6371 (patch)
treef84171501c3d98df394c94fcc6d32cc3dd5c6539
parent389f86b06d5f6129614cb312c7034cdc4bb1b684 (diff)
downloadIshtar-0c185f1abbe9abe0d977e1b7d1d3f0440b8d6371.tar.bz2
Ishtar-0c185f1abbe9abe0d977e1b7d1d3f0440b8d6371.zip
Locks: prevent edit actions
-rw-r--r--archaeological_context_records/forms.py10
-rw-r--r--archaeological_context_records/views.py7
-rw-r--r--archaeological_files/forms.py9
-rw-r--r--archaeological_files/views.py28
-rw-r--r--archaeological_finds/forms.py17
-rw-r--r--archaeological_finds/models_finds.py3
-rw-r--r--archaeological_finds/views.py10
-rw-r--r--archaeological_operations/forms.py20
-rw-r--r--archaeological_operations/views.py26
-rw-r--r--archaeological_warehouse/forms.py15
-rw-r--r--archaeological_warehouse/models.py5
-rw-r--r--archaeological_warehouse/views.py38
-rw-r--r--ishtar_common/forms.py8
-rw-r--r--ishtar_common/models.py2
-rw-r--r--ishtar_common/templates/ishtar/blocks/window_nav.html2
-rw-r--r--ishtar_common/urls.py3
-rw-r--r--ishtar_common/views.py15
17 files changed, 201 insertions, 17 deletions
diff --git a/archaeological_context_records/forms.py b/archaeological_context_records/forms.py
index 6bbc3099c..375943c9c 100644
--- a/archaeological_context_records/forms.py
+++ b/archaeological_context_records/forms.py
@@ -133,7 +133,15 @@ class RecordFormSelection(CustomFormSearch):
if 'pk' not in cleaned_data or not cleaned_data['pk']:
raise forms.ValidationError(_(u"You should at least select one "
u"context record."))
- return cleaned_data
+ pk = self.cleaned_data["pk"]
+ try:
+ cr = models.ContextRecord.objects.get(pk=pk)
+ except models.ContextRecord.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if cr.locked:
+ raise forms.ValidationError(_("This context record is locked for "
+ "edition."))
+ return self.cleaned_data
class RecordFormGeneral(CustomForm, ManageOldType):
diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py
index fe77150f6..794cb5592 100644
--- a/archaeological_context_records/views.py
+++ b/archaeological_context_records/views.py
@@ -144,6 +144,13 @@ def record_modify(request, pk):
)
return HttpResponseRedirect("/")
+ q = models.ContextRecord.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ cr = q.all()[0]
+ if cr.locked:
+ raise Http404()
+
wizards.RecordModifWizard.session_set_value(
request, 'selec-record_modification', 'pk', pk, reset=True)
return redirect(reverse('record_modification',
diff --git a/archaeological_files/forms.py b/archaeological_files/forms.py
index 8f18de29e..640e2cab1 100644
--- a/archaeological_files/forms.py
+++ b/archaeological_files/forms.py
@@ -140,7 +140,14 @@ class FileFormSelection(forms.Form):
cleaned_data = self.cleaned_data
if 'pk' not in cleaned_data or not cleaned_data['pk']:
raise forms.ValidationError(_(u"You should select a file."))
- return cleaned_data
+ pk = self.cleaned_data["pk"]
+ try:
+ file = models.File.objects.get(pk=pk)
+ except models.File.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if file.locked:
+ raise forms.ValidationError(_("This file is locked for edition."))
+ return self.cleaned_data
DATE_SOURCE = (('creation', _(u"Creation date")),
diff --git a/archaeological_files/views.py b/archaeological_files/views.py
index 50f3a86d2..e7307e882 100644
--- a/archaeological_files/views.py
+++ b/archaeological_files/views.py
@@ -22,16 +22,12 @@ import re
from django.core.urlresolvers import reverse
from django.db.models import Q
-from django.http import HttpResponse
-from django.shortcuts import redirect, render
+from django.http import HttpResponse, Http404, HttpResponseRedirect
+from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
from ishtar_common.views_item import get_item, show_item, revert_item
-from archaeological_operations.models import Operation
-from . import models
-
-from ishtar_common.wizards import SearchWizard
from archaeological_operations.wizards import AdministrativeActDeletionWizard, \
is_preventive, is_not_preventive
from .wizards import *
@@ -41,6 +37,8 @@ from archaeological_operations.forms import FinalAdministrativeActDeleteForm
from ishtar_common.forms import ClosingDateFormSelection
from . import forms
+from ishtar_common.utils import put_session_message
+
RE_YEAR_INDEX = re.compile(r"([1-2][0-9]{3})-([0-9]+)") # eg.: 2014-123
@@ -145,7 +143,23 @@ file_modification_wizard = FileModificationWizard.as_view(
def file_modify(request, pk):
- file_modification_wizard(request)
+ try:
+ file_modification_wizard(request)
+ except IndexError: # no step available
+ put_session_message(
+ request.session.session_key,
+ _(u"You don't have sufficient permissions to do this action."),
+ 'warning'
+ )
+ return HttpResponseRedirect("/")
+
+ q = models.File.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ item = q.all()[0]
+ if item.locked:
+ raise Http404()
+
FileModificationWizard.session_set_value(
request, 'selec-file_modification', 'pk', pk, reset=True)
return redirect(reverse('file_modification',
diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py
index f4b115492..4de4bdaf9 100644
--- a/archaeological_finds/forms.py
+++ b/archaeological_finds/forms.py
@@ -1239,6 +1239,7 @@ class FindFormSelection(CustomFormSearch):
form_label = _("Find search")
associated_models = {'pk': models.Find}
currents = {'pk': models.Find}
+ pk_key = 'pk'
pk = forms.IntegerField(
label="", required=False,
@@ -1249,6 +1250,22 @@ class FindFormSelection(CustomFormSearch):
source_full=reverse_lazy('get-find-full')),
validators=[valid_id(models.Find)])
+ def clean(self):
+ pk = self.cleaned_data[self.pk_key]
+ if "," in pk:
+ pks = [k.strip() for k in pk.split(',')]
+ else:
+ pks = [pk]
+ for pk in pks:
+ try:
+ find = models.Find.objects.get(pk=pk)
+ except models.Find.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if find.locked:
+ raise forms.ValidationError(
+ _("This find is locked for edition."))
+ return self.cleaned_data
+
class FindFormSelectionWarehouseModule(FindFormSelection):
pk = forms.IntegerField(
diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py
index 6914ff019..9b134bceb 100644
--- a/archaeological_finds/models_finds.py
+++ b/archaeological_finds/models_finds.py
@@ -1742,8 +1742,9 @@ class Find(BulkUpdatedItem, ValueGetter, DocumentItem, BaseHistorizedItem,
# own basket
actions = super(Find, self).get_extra_actions(request)
+ is_locked = getattr(self, "locked", False)
can_edit_find = self.can_do(request, 'change_find')
- if can_edit_find:
+ if can_edit_find and not is_locked:
actions += [
(reverse("find-qa-duplicate", args=[self.pk]),
_("Duplicate"), "fa fa-clone", "", "", True),
diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py
index 763733bd9..e5119b9f3 100644
--- a/archaeological_finds/views.py
+++ b/archaeological_finds/views.py
@@ -333,6 +333,8 @@ def find_modify(request, pk):
raise Http404()
step = 'find-find_modification'
find = q.all()[0]
+ if find.locked:
+ raise Http404()
if find.base_finds.count() > 1:
step = 'simplefind-find_modification'
@@ -973,6 +975,14 @@ class QAFindTreatmentFormView(QAItemForm):
page_name = _(u"Packaging")
base_url = "find-qa-packaging"
+ def dispatch(self, request, *args, **kwargs):
+ returned = super(QAFindTreatmentFormView, self).dispatch(
+ request, *args, **kwargs)
+ for item in self.items:
+ if item.locked:
+ return HttpResponseRedirect(reverse("qa-not-available"))
+ return returned
+
def get_form_kwargs(self):
kwargs = super(QAFindTreatmentFormView, self).get_form_kwargs()
kwargs['user'] = self.request.user
diff --git a/archaeological_operations/forms.py b/archaeological_operations/forms.py
index 5cc544171..1e12c3614 100644
--- a/archaeological_operations/forms.py
+++ b/archaeological_operations/forms.py
@@ -616,7 +616,15 @@ class OperationFormSelection(CustomFormSearch):
cleaned_data = self.cleaned_data
if 'pk' not in cleaned_data or not cleaned_data['pk']:
raise forms.ValidationError(_(u"You should select an operation."))
- return cleaned_data
+ pk = self.cleaned_data["pk"]
+ try:
+ item = models.Operation.objects.get(pk=pk)
+ except models.Operation.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if item.locked:
+ raise forms.ValidationError(_("This operation is locked for "
+ "edition."))
+ return self.cleaned_data
class OperationCodeInput(forms.TextInput):
@@ -1388,7 +1396,15 @@ class SiteFormSelection(IshtarForm):
cleaned_data = self.cleaned_data
if 'pk' not in cleaned_data or not cleaned_data['pk']:
raise forms.ValidationError(_(u"You should select an item."))
- return cleaned_data
+ pk = self.cleaned_data["pk"]
+ try:
+ item = models.ArchaeologicalSite.objects.get(pk=pk)
+ except models.ArchaeologicalSite.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if item.locked:
+ raise forms.ValidationError(_("This site is locked for "
+ "edition."))
+ return self.cleaned_data
class SiteForm(CustomForm, ManageOldType):
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index 4563f815e..d8d9f30d5 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -307,6 +307,14 @@ def operation_modify(request, pk):
'warning'
)
return HttpResponseRedirect("/")
+
+ q = models.Operation.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ item = q.all()[0]
+ if item.locked:
+ raise Http404()
+
OperationModificationWizard.session_set_value(
request, 'selec-operation_modification', 'pk', pk, reset=True)
return redirect(reverse('operation_modification',
@@ -392,7 +400,23 @@ site_modification_wizard = SiteModificationWizard.as_view(
def site_modify(request, pk):
- site_modification_wizard(request)
+ try:
+ site_modification_wizard(request)
+ except IndexError: # no step available
+ put_session_message(
+ request.session.session_key,
+ _(u"You don't have sufficient permissions to do this action."),
+ 'warning'
+ )
+ return HttpResponseRedirect("/")
+
+ q = models.ArchaeologicalSite.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ item = q.all()[0]
+ if item.locked:
+ raise Http404()
+
SiteModificationWizard.session_set_value(
request, 'selec-site_modification', 'pk', pk, reset=True)
return redirect(reverse('site_modification',
diff --git a/archaeological_warehouse/forms.py b/archaeological_warehouse/forms.py
index 94d37d092..ecf040a7e 100644
--- a/archaeological_warehouse/forms.py
+++ b/archaeological_warehouse/forms.py
@@ -121,6 +121,21 @@ class WarehouseFormSelection(forms.Form):
WarehouseSelect, models.Warehouse, gallery=True, map=True),
validators=[valid_id(models.Warehouse)])
+ def clean(self):
+ cleaned_data = self.cleaned_data
+ if 'pk' not in cleaned_data or not cleaned_data['pk']:
+ raise forms.ValidationError(_(u"You should select an item."))
+ pk = self.cleaned_data["pk"]
+ try:
+ item = models.Warehouse.objects.get(pk=pk)
+ except models.Warehouse.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ print(item)
+ if item.locked:
+ raise forms.ValidationError(_("This warehouse is locked for "
+ "edition."))
+ return self.cleaned_data
+
class WarehouseForm(CustomForm, ManageOldType, forms.Form):
HEADERS = {}
diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py
index 336046a86..a3cbf82e3 100644
--- a/archaeological_warehouse/models.py
+++ b/archaeological_warehouse/models.py
@@ -56,7 +56,8 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
APP = "archaeological-warehouse"
MODEL = "warehouse"
SHOW_URL = 'show-warehouse'
- TABLE_COLS = ['name', 'warehouse_type']
+ TABLE_COLS = ['name', 'warehouse_type__label']
+ NEW_QUERY_ENGINE = True
BASE_SEARCH_VECTORS = [
SearchVectorConfig("name"),
SearchVectorConfig("warehouse_type__label"),
@@ -66,6 +67,7 @@ class Warehouse(Address, DocumentItem, GeoItem, QRCodeItem, DashboardFormItem,
]
EXTRA_REQUEST_KEYS = {
+ "warehouse_type__label": "warehouse_type__label",
# used by dynamic_table_documents
"person_in_charge__pk": "person_in_charge__pk",
}
@@ -414,6 +416,7 @@ class Container(DocumentItem, LightHistorizedItem, QRCodeItem, GeoItem,
APP = "archaeological-warehouse"
MODEL = "container"
SHOW_URL = 'show-container'
+ NEW_QUERY_ENGINE = True
TABLE_COLS = ['reference', 'container_type__label', 'cached_location',
'cached_division', 'old_reference']
IMAGE_PREFIX = 'containers/'
diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py
index 85b5511ae..ecbcc3175 100644
--- a/archaeological_warehouse/views.py
+++ b/archaeological_warehouse/views.py
@@ -21,7 +21,7 @@ import json
from django.core.urlresolvers import reverse
from django.db.models import Q
-from django.http import HttpResponse, Http404
+from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _
@@ -42,6 +42,8 @@ from archaeological_warehouse.wizards import PackagingWizard, WarehouseSearch, \
ContainerSearch, ContainerWizard, ContainerModificationWizard, \
ContainerDeletionWizard
+from ishtar_common.utils import put_session_message
+
get_container = get_item(models.Container, 'get_container', 'container',
search_form=ContainerSelect)
show_container = show_item(models.Container, 'container')
@@ -146,6 +148,23 @@ warehouse_modification_wizard = WarehouseModificationWizard.as_view([
def warehouse_modify(request, pk):
+ try:
+ warehouse_modification_wizard(request)
+ except IndexError: # no step available
+ put_session_message(
+ request.session.session_key,
+ _(u"You don't have sufficient permissions to do this action."),
+ 'warning'
+ )
+ return HttpResponseRedirect("/")
+
+ q = models.Warehouse.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ item = q.all()[0]
+ if item.locked:
+ raise Http404()
+
WarehouseModificationWizard.session_set_value(
request, 'selec-warehouse_modification', 'pk', pk, reset=True)
return redirect(
@@ -187,6 +206,23 @@ container_modification_wizard = ContainerModificationWizard.as_view([
def container_modify(request, pk):
+ try:
+ container_modification_wizard(request)
+ except IndexError: # no step available
+ put_session_message(
+ request.session.session_key,
+ _(u"You don't have sufficient permissions to do this action."),
+ 'warning'
+ )
+ return HttpResponseRedirect("/")
+
+ q = models.Container.objects.filter(pk=pk)
+ if not q.count():
+ raise Http404()
+ item = q.all()[0]
+ if item.locked:
+ raise Http404()
+
ContainerModificationWizard.session_set_value(
request, 'selec-container_modification', 'pk', pk, reset=True)
return redirect(
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index 1f4d50d60..a69c65f0e 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -735,6 +735,14 @@ def get_form_selection(
if self._main_key not in cleaned_data \
or not cleaned_data[self._main_key]:
raise forms.ValidationError(self._not_selected_error)
+
+ pk = self.cleaned_data[self._main_key]
+ try:
+ item = model.objects.get(pk=pk)
+ except model.DoesNotExist:
+ raise forms.ValidationError(_("Invalid selection."))
+ if hasattr(item, "locked") and item.locked:
+ raise forms.ValidationError(_("This item is locked for edition."))
return cleaned_data
attrs['clean'] = clean
attrs['SEARCH_AND_SELECT'] = True
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index bc9e68c02..f673aed85 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -1825,7 +1825,7 @@ class DocumentItem(object):
return actions
can_add_doc = self.can_do(request, 'add_document')
- if can_add_doc:
+ if can_add_doc and not getattr(self, "locked", False):
actions = [
(
reverse("create-document") + "?{}={}".format(
diff --git a/ishtar_common/templates/ishtar/blocks/window_nav.html b/ishtar_common/templates/ishtar/blocks/window_nav.html
index d76ff49e1..19b70ccd6 100644
--- a/ishtar_common/templates/ishtar/blocks/window_nav.html
+++ b/ishtar_common/templates/ishtar/blocks/window_nav.html
@@ -44,7 +44,7 @@
{% endif %}
<div class="btn-group btn-group-sm" role="group" aria-label="{% trans 'Actions' %}">
{% block extra_actions %}{% endblock %}
- {% if modify_url %}
+ {% if modify_url and not item.locked %}
<a class="btn btn-success wait-button" href='{% url modify_url item.pk %}'
title="{% trans 'Modify' %}">
<i class="fa fa-pencil"></i>
diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py
index 3667d46b2..13694b10f 100644
--- a/ishtar_common/urls.py
+++ b/ishtar_common/urls.py
@@ -291,6 +291,9 @@ urlpatterns += [
check_rights(['change_document', 'change_own_document'])(
views.QADocumentForm.as_view()),
name='document-qa-bulk-update-confirm', kwargs={"confirm": True}),
+
+ url(r'^qa-not-available/$', views.QANotAvailable.as_view(),
+ name='qa-not-available'),
]
urlpatterns += get_urls_for_model(models.Document, views)
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index 2af082a0a..4ab94aae9 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -2110,6 +2110,17 @@ class AlertList(JSONResponseMixin, LoginRequiredMixin,
return {'alerts': alerts}
+class QANotAvailable(IshtarMixin, LoginRequiredMixin, TemplateView):
+ template_name = 'ishtar/forms/qa_message.html'
+ modal_size = "small"
+
+ def get_context_data(self, **kwargs):
+ data = super(QANotAvailable, self).get_context_data(**kwargs)
+ data["page_name"] = _("Not available")
+ data['message'] = _("Action not available for these items.")
+ return data
+
+
class QAItemForm(IshtarMixin, LoginRequiredMixin, FormView):
template_name = 'ishtar/forms/qa_form.html'
model = None
@@ -2168,6 +2179,10 @@ class QAItemEditForm(QAItemForm):
self.confirm = kwargs.get('confirm', False) and True
returned = super(QAItemEditForm, self).dispatch(request, *args,
**kwargs)
+ if hasattr(self.model, "locked"):
+ for item in self.items:
+ if item.locked:
+ return HttpResponseRedirect(reverse("qa-not-available"))
return returned
def get_form_class(self):