Skip to content

Commit

Permalink
Merge pull request #633 from Cadasta/bugfix/#590
Browse files Browse the repository at this point in the history
Fix #590: spatial unit visibility
  • Loading branch information
linzjax authored Sep 2, 2016
2 parents aec22a7 + 3b428ab commit 81789a0
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 22 deletions.
5 changes: 4 additions & 1 deletion cadasta/accounts/load.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from tutelary import models


def run(verbose=True, force=False):
def run(verbose=True, force=False, update=False):
PERMISSIONS_DIR = settings.BASE_DIR + '/permissions/'

if force:
Expand All @@ -16,6 +16,9 @@ def run(verbose=True, force=False):
'project-manager', 'data-collector', 'project-user']:
try:
pols[pol] = models.Policy.objects.get(name=pol)
if update:
pols[pol].body = open(PERMISSIONS_DIR + pol + '.json').read()
pols[pol].save()
except:
pols[pol] = models.Policy.objects.create(
name=pol,
Expand Down
2 changes: 1 addition & 1 deletion cadasta/accounts/management/commands/loadpolicies.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ class Command(BaseCommand):
help = """Loads policy data."""

def handle(self, *args, **options):
load.run(force=options['force'])
load.run(force=options['force'], update=options['update'])
8 changes: 8 additions & 0 deletions cadasta/config/permissions/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@
"effect": "allow",
"action": ["project.view"],
"object": ["project/*/*"]
},

{
// Any user is allowed to list the spatial units of public
// projects in an organization.
"effect": "allow",
"action": ["spatial.list"],
"object": ["project/*/*"]
}
]
}
37 changes: 24 additions & 13 deletions cadasta/core/management/commands/loadstatic.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,30 @@ def add_arguments(self, parser):
default=False,
help='Force object deletion and recreation'
)
parser.add_argument(
'--update-policies',
action='store_true',
dest='update_policies',
default=False,
help='Force update of tutelary policies from JSON files'
)

def handle(self, *args, **options):
# All of the following are idempotent unless "force" is used.
if options['force']:
print('FORCING STATIC DATA RELOAD!!!\n')
if options['update_policies']:
print('PERFORMING POLICY UPDATE FROM FILES!!!\n')
loadpolicies.Command().handle(force=False, update=True)
else:
# All of the following are idempotent unless "force" is used.
if options['force']:
print('FORCING STATIC DATA RELOAD!!!\n')

print('LOADING SITE\n')
loadsite.Command().handle(force=options['force'])
print('LOADING COUNTRIES\n')
loadcountries.Command().handle(force=options['force'])
print('LOADING POLICIES\n')
loadpolicies.Command().handle(force=options['force'])
print('LOADING ATTRIBUTE TYPES\n')
loadattrtypes.Command().handle(force=options['force'])
print('LOADING TENURE RELATIONSHIP TYPES\n')
loadtenurereltypes.Command().handle(force=options['force'])
print('LOADING SITE\n')
loadsite.Command().handle(force=options['force'])
print('LOADING COUNTRIES\n')
loadcountries.Command().handle(force=options['force'])
print('LOADING POLICIES\n')
loadpolicies.Command().handle(force=options['force'])
print('LOADING ATTRIBUTE TYPES\n')
loadattrtypes.Command().handle(force=options['force'])
print('LOADING TENURE RELATIONSHIP TYPES\n')
loadtenurereltypes.Command().handle(force=options['force'])
4 changes: 2 additions & 2 deletions cadasta/core/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ def _adjust_kwargs(cls, **kwargs):
kwargs['body'] = open(body_file).read()
return kwargs

def load_policies():
load.run(force=True)
def load_policies(update=False):
load.run(force=not update, update=update)


class RoleFactory(factory.django.DjangoModelFactory):
Expand Down
2 changes: 2 additions & 0 deletions cadasta/core/tests/test_management_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ def test_fixture_setup(self):
data.delete_test_projects()
data.add_test_organizations()
PolicyFactory.load_policies()
# Just for test coverage...
PolicyFactory.load_policies(update=True)
create_attribute_types()
load_tenure_relationship_types()
data.add_test_users_and_roles()
Expand Down
8 changes: 8 additions & 0 deletions cadasta/spatial/tests/test_views_api_spatial_units.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.auth.models import AnonymousUser
from django.utils.translation import gettext as _
from rest_framework import status as status_code

Expand Down Expand Up @@ -50,6 +51,13 @@ def test_full_list(self):
assert extra_record.id not in (
[u['properties']['id'] for u in content['features']])

def test_full_list_with_unauthorized_user(self):
org, prj = self._test_objs()
self._get(
org_slug=org.slug, prj_slug=prj.slug, user=AnonymousUser(),
status=status_code.HTTP_200_OK, length=self.num_records
)

# def test_search_filter(self):
# org, prj = self._test_objs()
# content = self._get(
Expand Down
3 changes: 1 addition & 2 deletions cadasta/spatial/tests/test_views_default.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,7 @@ def test_get_from_non_existend_project(self):
def test_get_with_unauthorized_user(self):
response, content = self.request(user=self.unauthorized_user)
assert response.status_code == 200
assert content == self.expected_content(
geojson='{"type": "FeatureCollection", "features": []}')
assert content == self.expected_content()

def test_get_with_unauthenticated_user(self):
response = self.request()
Expand Down
7 changes: 6 additions & 1 deletion cadasta/spatial/views/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
class SpatialUnitList(APIPermissionRequiredMixin,
mixins.SpatialQuerySetMixin,
generics.ListCreateAPIView):
def get_actions(self, request):
if self.get_project().public():
return ['project.view', 'spatial.list']
else:
return ['project.view_private', 'spatial.list']

serializer_class = serializers.SpatialUnitSerializer
filter_backends = (filters.DjangoFilterBackend,
Expand All @@ -17,7 +22,7 @@ class SpatialUnitList(APIPermissionRequiredMixin,
filter_fields = ('type',)

permission_required = {
'GET': 'spatial.list',
'GET': get_actions,
'POST': 'spatial.create',
}

Expand Down
1 change: 0 additions & 1 deletion cadasta/spatial/views/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ class LocationsList(LoginPermissionRequiredMixin,
template_name = 'spatial/location_map.html'
permission_required = 'spatial.list'
permission_denied_message = error_messages.SPATIAL_LIST
permission_filter_queryset = ('spatial.view',)


class LocationsAdd(LoginPermissionRequiredMixin,
Expand Down
5 changes: 4 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ envlist =

[testenv]
passenv = DJANGO_SETTINGS_MODULE
setenv = PYTHONDONTWRITEBYTECODE=1
setenv =
PYTHONDONTWRITEBYTECODE=1
CPLUS_INCLUDE_PATH=/usr/include/gdal
C_INCLUDE_PATH=/usr/include/gdal
deps = -r{toxinidir}/requirements/dev.txt
install_command = pip install --find-links https://s3.amazonaws.com:443/cadasta-wheelhouse/index.html {opts} {packages}

Expand Down

0 comments on commit 81789a0

Please sign in to comment.