summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--archaeological_operations/models.py9
-rw-r--r--archaeological_operations/tests.py105
-rw-r--r--archaeological_operations/views.py14
-rw-r--r--ishtar_common/models.py16
-rw-r--r--ishtar_common/tests.py4
-rw-r--r--ishtar_common/utils.py2
-rw-r--r--ishtar_common/wizards.py18
7 files changed, 152 insertions, 16 deletions
diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py
index c342fb2a4..9655ca387 100644
--- a/archaeological_operations/models.py
+++ b/archaeological_operations/models.py
@@ -698,11 +698,18 @@ class Operation(ClosedItem, BaseHistorizedItem, ImageModel, OwnPerms,
@classmethod
def get_query_owns(cls, ishtaruser):
+ profile = ishtaruser.current_profile
+ town_ids = []
+ if profile:
+ town_ids = [town['pk']
+ for town in profile.query_towns.values('pk').all()]
return (
Q(in_charge=ishtaruser.person) |
Q(scientist=ishtaruser.person) |
Q(collaborators__pk=ishtaruser.person.pk) |
- Q(history_creator=ishtaruser.user_ptr)) & Q(end_date__isnull=True)
+ Q(history_creator=ishtaruser.user_ptr) |
+ Q(towns__pk__in=town_ids)
+ ) & Q(end_date__isnull=True)
def is_active(self):
return not bool(self.end_date)
diff --git a/archaeological_operations/tests.py b/archaeological_operations/tests.py
index 7cfa83435..299ed49f8 100644
--- a/archaeological_operations/tests.py
+++ b/archaeological_operations/tests.py
@@ -41,7 +41,8 @@ from ishtar_common.models import OrganizationType, Organization, ItemKey, \
ImporterType, IshtarUser, TargetKey, ImporterModel, IshtarSiteProfile, \
Town, ImporterColumn, Person, Author, SourceType, AuthorType, \
DocumentTemplate, PersonType, TargetKeyGroup, JsonDataField, \
- JsonDataSection, ImportTarget, FormaterType, CustomForm, ExcludedField
+ JsonDataSection, ImportTarget, FormaterType, CustomForm, ExcludedField, \
+ UserProfile, ProfileType, Area
from archaeological_files.models import File, FileType
from archaeological_context_records.models import Unit, ContextRecord
@@ -1372,6 +1373,20 @@ class OperationSearchTest(TestCase, OperationInitTest):
self.alt_username, self.alt_password, self.alt_user = create_user()
self.alt_user.user_permissions.add(Permission.objects.get(
codename='view_own_operation'))
+ self.alt_user.user_permissions.add(Permission.objects.get(
+ codename='change_own_operation'))
+ self.alt_username2, self.alt_password2, self.alt_user2 = create_user(
+ username='luke', password='iamyourfather'
+ )
+ profile = UserProfile.objects.create(
+ profile_type=ProfileType.objects.get(txt_idx='collaborator'),
+ person=self.alt_user2.ishtaruser.person
+ )
+ town = Town.objects.create(name='Tatouine', numero_insee='66000')
+ area = Area.objects.create(label='Galaxie', txt_idx='galaxie')
+ area.towns.add(town)
+ profile.areas.add(area)
+
self.orgas = self.create_orgas(self.user)
self.operations = self.create_operation(self.user, self.orgas[0])
self.operations += self.create_operation(self.alt_user, self.orgas[0])
@@ -1407,7 +1422,6 @@ class OperationSearchTest(TestCase, OperationInitTest):
result = json.loads(response.content)
self.assertEqual(result['recordsTotal'], 1)
-
def create_relations(self):
rel1 = models.RelationType.objects.create(
symmetrical=True, label='Include', txt_idx='include')
@@ -1504,19 +1518,102 @@ class OperationSearchTest(TestCase, OperationInitTest):
self.assertEqual(response.status_code, 200)
self.assertEqual(json.loads(response.content)['recordsTotal'], 1)
- def testOwnSearch(self):
+
+class OperationPermissionTest(TestCase, OperationInitTest):
+ fixtures = FILE_FIXTURES
+
+ def setUp(self):
+ IshtarSiteProfile.objects.get_or_create(
+ slug='default', active=True)
+ self.username, self.password, self.user = create_superuser()
+ self.alt_username, self.alt_password, self.alt_user = create_user()
+ self.alt_user.user_permissions.add(Permission.objects.get(
+ codename='view_own_operation'))
+ self.alt_user.user_permissions.add(Permission.objects.get(
+ codename='change_own_operation'))
+ self.alt_username2, self.alt_password2, self.alt_user2 = create_user(
+ username='luke', password='iamyourfather'
+ )
+ profile = UserProfile.objects.create(
+ profile_type=ProfileType.objects.get(txt_idx='collaborator'),
+ person=self.alt_user2.ishtaruser.person,
+ current=True
+ )
+ town = Town.objects.create(name='Tatouine', numero_insee='66000')
+ area = Area.objects.create(label='Galaxie', txt_idx='galaxie')
+ area.towns.add(town)
+ profile.areas.add(area)
+
+ self.orgas = self.create_orgas(self.user)
+ self.operations = self.create_operation(self.user, self.orgas[0])
+ self.operations += self.create_operation(self.alt_user, self.orgas[0])
+ self.operations[1].towns.add(town)
+ self.item = self.operations[0]
+
+ def test_own_search(self):
+ # no result when no authentification
c = Client()
response = c.get(reverse('get-operation'), {'year': '2010'})
- # no result when no authentification
self.assertTrue(not json.loads(response.content))
+
+ # possession
+ c = Client()
c.login(username=self.alt_username, password=self.alt_password)
response = c.get(reverse('get-operation'), {'year': '2010'})
# only one "own" operation available
+ self.assertTrue(json.loads(response.content))
+ self.assertTrue(json.loads(response.content)['recordsTotal'] == 1)
+ response = c.get(reverse('get-operation'),
+ {'operator': self.orgas[0].pk})
+ self.assertTrue(json.loads(response.content)['recordsTotal'] == 1)
+
+ # area filter
+ c = Client()
+ c.login(username=self.alt_username2, password=self.alt_password2)
+ response = c.get(reverse('get-operation'), {'year': '2010'})
+ # only one "own" operation available
+ self.assertTrue(json.loads(response.content))
self.assertTrue(json.loads(response.content)['recordsTotal'] == 1)
response = c.get(reverse('get-operation'),
{'operator': self.orgas[0].pk})
self.assertTrue(json.loads(response.content)['recordsTotal'] == 1)
+ def test_own_modify(self):
+ operation_pk1 = self.operations[0].pk
+ operation_pk2 = self.operations[1].pk
+
+ # no result when no authentification
+ c = Client()
+ response = c.get(reverse('operation_modify', args=[operation_pk2]))
+ self.assertRedirects(response, "/")
+
+ modif_url = '/operation_modification/general-operation_modification'
+
+ # possession
+ c = Client()
+ c.login(username=self.alt_username, password=self.alt_password)
+ response = c.get(reverse('operation_modify', args=[operation_pk2]),
+ follow=True)
+ self.assertRedirects(response, modif_url)
+ response = c.get(modif_url)
+ self.assertEqual(response.status_code, 200)
+ response = c.get(reverse('operation_modify', args=[operation_pk1]),
+ follow=True)
+ self.assertRedirects(response, "/")
+
+ # area filter
+ c = Client()
+ c.login(username=self.alt_username2, password=self.alt_password2)
+ response = c.get(reverse('operation_modify', args=[operation_pk2]),
+ follow=True)
+ self.assertRedirects(response, modif_url)
+ response = c.get(modif_url)
+ self.assertEqual(response.status_code, 200)
+ response = c.get(reverse('operation_modify', args=[operation_pk1]),
+ follow=True)
+ self.assertRedirects(response, "/")
+
+
class DashboardTest(TestCase, OperationInitTest):
fixtures = FILE_FIXTURES
diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py
index fcd6c3252..e7e624c05 100644
--- a/archaeological_operations/views.py
+++ b/archaeological_operations/views.py
@@ -22,7 +22,7 @@ import json
from django.conf import settings
from django.core.urlresolvers import reverse
from django.db.models import Q
-from django.http import HttpResponse
+from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.utils.translation import ugettext_lazy as _, pgettext_lazy
@@ -58,6 +58,8 @@ from archaeological_operations.wizards import has_associated_file, \
AdministrativeActDeletionWizard, SiteWizard, SiteModificationWizard, \
SiteDeletionWizard
+from ishtar_common.utils import put_session_message
+
def autocomplete_patriarche(request):
if (not request.user.has_perm('ishtar_common.view_operation',
@@ -303,7 +305,15 @@ operation_modification_wizard = OperationModificationWizard.as_view(
def operation_modify(request, pk):
- operation_modification_wizard(request)
+ try:
+ operation_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("/")
OperationModificationWizard.session_set_value(
request, 'selec-operation_modification', 'pk', pk, reset=True)
return redirect(reverse('operation_modification',
diff --git a/ishtar_common/models.py b/ishtar_common/models.py
index 67c4422f6..2ebe07961 100644
--- a/ishtar_common/models.py
+++ b/ishtar_common/models.py
@@ -2693,6 +2693,15 @@ class UserProfile(models.Model):
[unicode(area) for area in self.areas.all()]))
@property
+ def query_towns(self):
+ return Town.objects.filter(
+ Q(areas__profiles=self) | Q(areas__parent__profiles=self) |
+ Q(areas__parent__parent__profiles=self) |
+ Q(areas__parent__parent__parent__profiles=self) |
+ Q(areas__parent__parent__parent__parent__profiles=self)
+ )
+
+ @property
def area_labels(self):
return u", ".join([unicode(area) for area in self.areas.all()])
@@ -2743,6 +2752,10 @@ class IshtarUser(FullSearch):
return u""
return unicode(profile)
+ @property
+ def current_profile(self):
+ return self.person.current_profile
+
@classmethod
def set_superuser(cls, user):
q = cls.objects.filter(user_ptr=user)
@@ -3141,7 +3154,8 @@ m2m_changed.connect(town_child_changed, sender=Town.children.through)
class Area(HierarchicalType):
- towns = models.ManyToManyField(Town, verbose_name=_(u"Towns"), blank=True)
+ towns = models.ManyToManyField(Town, verbose_name=_(u"Towns"), blank=True,
+ related_name='areas')
parent = models.ForeignKey(
'self', blank=True, null=True, verbose_name=_(u"Parent"),
help_text=_(u"Only four level of parent are managed.")
diff --git a/ishtar_common/tests.py b/ishtar_common/tests.py
index 4ee47d723..0d606476d 100644
--- a/ishtar_common/tests.py
+++ b/ishtar_common/tests.py
@@ -79,9 +79,7 @@ def create_superuser():
return username, password, user
-def create_user():
- username = 'username678'
- password = 'dcbqj756aaa456!@%'
+def create_user(username='username678', password='dcbqj756aaa456!@%'):
q = User.objects.filter(username=username)
if q.count():
return username, password, q.all()[0]
diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py
index b03e794d0..01b35dcef 100644
--- a/ishtar_common/utils.py
+++ b/ishtar_common/utils.py
@@ -381,7 +381,7 @@ def put_session_message(session_key, message, message_type):
messages = []
if 'messages' in session:
messages = session['messages'][:]
- messages.append((message, message_type))
+ messages.append((unicode(message), message_type))
session['messages'] = messages
session.save()
diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py
index 5f3da1130..9e77a0dda 100644
--- a/ishtar_common/wizards.py
+++ b/ishtar_common/wizards.py
@@ -43,7 +43,8 @@ from django.utils.safestring import mark_safe
from ishtar_common import models
from ishtar_common.forms import CustomForm, reverse_lazy
-from ishtar_common.utils import get_all_field_names, MultiValueDict
+from ishtar_common.utils import get_all_field_names, MultiValueDict, \
+ put_session_message
logger = logging.getLogger(__name__)
@@ -69,6 +70,11 @@ def check_rights(rights=[], redirect_url='/'):
request.session):
kwargs['current_right'] = right
return view_func(request, *args, **kwargs)
+ put_session_message(
+ request.session.session_key,
+ _(u"You don't have sufficient permissions to do this action."),
+ 'warning'
+ )
return HttpResponseRedirect(redirect_url)
return _wrapped_view
return decorator
@@ -110,6 +116,8 @@ def _check_right(step, condition=True):
def filter_no_fields_form(form, other_check=None):
def func(self):
+ if not hasattr(self.request.user, 'ishtaruser'):
+ return False
if issubclass(form, CustomForm):
enabled, exc = form.check_availability_and_excluded_fields(
self.request.user.ishtaruser)
@@ -184,9 +192,11 @@ class Wizard(NamedUrlWizardView):
self.steps = StepsHelper(self)
current_object = self.get_current_object()
+ 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(request.user):
+ current_object and not current_object.is_own(ishtaruser):
self.session_reset(request, self.url_name)
return HttpResponseRedirect('/')
# extra filter on forms
@@ -206,8 +216,8 @@ class Wizard(NamedUrlWizardView):
def get_prefix(self, request, *args, **kwargs):
"""As the class name can interfere when reused prefix with the url_name
"""
- return self.url_name + super(Wizard, self).get_prefix(
- request, *args, **kwargs)
+ return self.url_name + super(Wizard, self).get_prefix(request, *args,
+ **kwargs)
def get_wizard_name(self):
"""As the class name can interfere when reused, use the url_name"""