diff --git a/cadasta/core/fixtures.py b/cadasta/core/fixtures.py index 2cf32b445..2b8b67a0b 100644 --- a/cadasta/core/fixtures.py +++ b/cadasta/core/fixtures.py @@ -128,7 +128,7 @@ def add_test_projects(self): This is a test project. This is a test project. This is a test project. This is a test project. This is a test project. This is a test project. This is a test project.""", - organization=orgs[0], + organization=orgs[1], country='KE', extent=('SRID=4326;' 'POLYGON ((-5.1031494140625000 8.1299292850467957, ' @@ -144,7 +144,7 @@ def add_test_projects(self): This is a test project. This is a test project. This is a test project. This is a test project. This is a test project. This is a test project. This is a test project.""", - organization=orgs[0], + organization=orgs[1], country='PH', extent=('SRID=4326;' 'POLYGON ((-63.6328125000000000 44.7233201889582475, ' @@ -161,7 +161,7 @@ def add_test_projects(self): project. This is another test project. This is a test project. This is another test project. This is another test project. This is another test project.""", - organization=orgs[1], + organization=orgs[0], country='ID', extent=('SRID=4326;' 'POLYGON ((-57.0520019531250000 -1.0793428942462329, ' @@ -179,7 +179,7 @@ def add_test_projects(self): project. This is another test project. This is a test project. This is another test project. This is another test project. This is another test project.""", - organization=orgs[1], + organization=orgs[0], country='MM' )) projs.append(ProjectFactory.create( @@ -190,7 +190,7 @@ def add_test_projects(self): project. This is another test project. This is a test project. This is another test project. This is another test project. This is another test project.""", - organization=orgs[1], + organization=orgs[0], country='MM', extent=GEOSGeometry( '{"type": "Polygon",' @@ -212,7 +212,7 @@ def add_test_projects(self): project. This is another test project. This is a test project. This is another test project. This is another test project. This is another test project.""", - organization=orgs[1], + organization=orgs[0], country='MM', extent=GEOSGeometry( '{"type": "Polygon",' @@ -233,7 +233,7 @@ def add_test_projects(self): project. This is another test project. This is a test project. This is another test project. This is another test project. This is another test project.""", - organization=orgs[0], + organization=orgs[1], extent=GEOSGeometry( '{"type": "Polygon",' '"coordinates": [[' @@ -251,6 +251,48 @@ def add_test_projects(self): '[-245.3981566429138, -3.331934566552203],' '[-245.39695501327512, -3.328635665488632]]]}') )) + + projs.append(ProjectFactory.create( + name='Private Cadasta Test Project', + slug='private-cadasta', + description=""""This is a private test project. This is pivate test + project. This is pivate test project. This is pivate test + project. This is pivate test project. This is a test project. + This is another test project. This is another test project. + This is another test project.""", + organization=orgs[0], + extent=GEOSGeometry( + '{"type": "Polygon",' + '"coordinates": [[' + '[-21.81009292602539, 64.07722793795327],' + '[-21.81009292602539, 64.09425757251603],' + '[-21.76013946533203, 64.09425757251603],' + '[-21.76013946533203, 64.07722793795327],' + '[-21.81009292602539, 64.07722793795327]]' + ']}'), + access='private' + )) + + projs.append(ProjectFactory.create( + name='Private H4H Test Project', + slug='private-h4h', + description=""""This is a private test project. This is pivate test + project. This is pivate test project. This is pivate test + project. This is pivate test project. This is a test project. + This is another test project. This is another test project. + This is another test project.""", + organization=orgs[1], + extent=GEOSGeometry( + '{"type": "Polygon",' + '"coordinates": [[' + '[-166.18331909179688, 59.891003681240576],' + '[-166.18331909179688, 60.06346983332297],' + '[-165.596923828125, 60.06346983332297],' + '[-165.596923828125, 59.891003681240576],' + '[-166.18331909179688, 59.891003681240576]]]}'), + access='private' + )) + print('\nSuccessfully added organizations {}'. format(Project.objects.all())) diff --git a/cadasta/core/tests/test_fixtures.py b/cadasta/core/tests/test_fixtures.py index c55dfad7c..2333895c5 100644 --- a/cadasta/core/tests/test_fixtures.py +++ b/cadasta/core/tests/test_fixtures.py @@ -21,7 +21,7 @@ def test_fixture_setup(self): assert User.objects.count() == 20 assert Policy.objects.count() == 7 assert Organization.objects.count() == 2 - assert Project.objects.count() == 7 + assert Project.objects.count() == 9 assert SpatialUnit.objects.count() == 7 assert SpatialUnitRelationship.objects.count() == 2 diff --git a/cadasta/core/tests/test_views_default.py b/cadasta/core/tests/test_views_default.py index d1da8d590..36f839037 100644 --- a/cadasta/core/tests/test_views_default.py +++ b/cadasta/core/tests/test_views_default.py @@ -1,8 +1,15 @@ +import json + from django.test import TestCase from django.http import HttpRequest from django.contrib.auth.models import AnonymousUser +from django.template import RequestContext +from django.template.loader import render_to_string from accounts.tests.factories import UserFactory +from organization.tests.factories import OrganizationFactory, ProjectFactory +from organization.models import OrganizationRole, Project +from organization.serializers import ProjectGeometrySerializer from ..views.default import IndexPage, Dashboard @@ -31,8 +38,40 @@ def setUp(self): self.view = Dashboard.as_view() self.request = HttpRequest() setattr(self.request, 'method', 'GET') + self.org = OrganizationFactory.create() + extent = ('SRID=4326;' + 'POLYGON ((-5.1031494140625000 8.1299292850467957, ' + '-5.0482177734375000 7.6837733211111425, ' + '-4.6746826171875000 7.8252894725496338, ' + '-4.8641967773437491 8.2278005261522775, ' + '-5.1031494140625000 8.1299292850467957))') + ProjectFactory.create(organization=self.org, extent=extent) + ProjectFactory.create(organization=self.org, extent=extent) + ProjectFactory.create( + name='Private Project', + access='private', organization=self.org, extent=extent) + setattr(self.request, 'user', AnonymousUser()) + def _test_projects_rendered(self, response, member=False): + content = response.render().content.decode('utf-8') + + context = RequestContext(self.request) + projects = [] + if member: + projects.extend(Project.objects.filter( + organization__slug=self.org.slug, access='private')) + projects.extend(Project.objects.filter(access='public')) + context['geojson'] = json.dumps( + ProjectGeometrySerializer(projects, many=True).data + ) + expected = render_to_string( + 'core/dashboard.html', + context + ) + + assert expected == content + def test_redirects_when_user_is_not_signed_in(self): response = self.view(self.request) assert response.status_code == 302 @@ -43,3 +82,18 @@ def test_page_is_rendered_when_user_is_signed_in(self): setattr(self.request, 'user', user) response = self.view(self.request) assert response.status_code == 200 + + def test_private_projects_rendered_when_org_member_is_signed_in(self): + user = UserFactory.create() + OrganizationRole.objects.create(organization=self.org, user=user) + setattr(self.request, 'user', user) + response = self.view(self.request) + assert response.status_code == 200 + self._test_projects_rendered(response, member=True) + + def test_private_projects_not_rendered_when_not_an_org_member(self): + user = UserFactory.create() + setattr(self.request, 'user', user) + response = self.view(self.request) + assert response.status_code == 200 + self._test_projects_rendered(response) diff --git a/cadasta/core/views/default.py b/cadasta/core/views/default.py index e334d78c5..f0b99b9d7 100644 --- a/cadasta/core/views/default.py +++ b/cadasta/core/views/default.py @@ -3,7 +3,7 @@ from django.shortcuts import redirect from django.views.generic import TemplateView from django.contrib.auth.mixins import LoginRequiredMixin -from organization.models import Project +from organization.models import Project, Organization from organization.serializers import ProjectGeometrySerializer @@ -21,10 +21,21 @@ def get(self, request, *args, **kwargs): class Dashboard(LoginRequiredMixin, TemplateView): template_name = 'core/dashboard.html' - def get_context_data(self, **kwargs): + def get_context_data(self, projects, **kwargs): context = super().get_context_data(**kwargs) - projects = Project.objects.filter(extent__isnull=False) + projects.extend(Project.objects.filter(access='public')) context['geojson'] = json.dumps( ProjectGeometrySerializer(projects, many=True).data ) return context + + def get(self, request, *args, **kwargs): + projects = [] + if hasattr(self.request.user, 'organizations'): + user_orgs = self.request.user.organizations.all() + if len(user_orgs) > 0: + for org in Organization.objects.all(): + if org in user_orgs: + projects.extend(org.projects.filter(access='private')) + context = self.get_context_data(projects=projects) + return super(TemplateView, self).render_to_response(context) diff --git a/cadasta/organization/models.py b/cadasta/organization/models.py index 641207f90..5abe6c4fa 100644 --- a/cadasta/organization/models.py +++ b/cadasta/organization/models.py @@ -97,6 +97,12 @@ def __str__(self): def __repr__(self): return str(self) + def public_projects(self): + return self.projects.filter(access='public') + + def all_projects(self): + return self.projects.all() + class OrganizationRole(RandomIDModel): organization = models.ForeignKey(Organization) diff --git a/cadasta/organization/tests/test_views_default_organizations.py b/cadasta/organization/tests/test_views_default_organizations.py index 18b655338..266249bf6 100644 --- a/cadasta/organization/tests/test_views_default_organizations.py +++ b/cadasta/organization/tests/test_views_default_organizations.py @@ -11,9 +11,9 @@ from accounts.tests.factories import UserFactory from ..views import default -from ..models import Organization, OrganizationRole +from ..models import Organization, OrganizationRole, Project from .. import forms -from .factories import OrganizationFactory, clause +from .factories import OrganizationFactory, ProjectFactory, clause class OrganizationListTest(TestCase): @@ -137,6 +137,9 @@ def setUp(self): setattr(self.request, 'method', 'GET') self.org = OrganizationFactory.create() + self.projs = ProjectFactory.create_batch(2, organization=self.org) + self.private_proj = ProjectFactory.create( + organization=self.org, access='private') clauses = { 'clause': [ @@ -155,17 +158,29 @@ def setUp(self): self.user = UserFactory.create() setattr(self.request, 'user', self.user) - def _get(self, slug, status=None): + def _get(self, slug, status=None, user=None, make_org_member=None,): + if user is None: + user = self.user + if make_org_member is not None: + OrganizationRole.objects.create(organization=self.org, user=user) + setattr(self.request, 'user', user) response = self.view(self.request, slug=slug) if status is not None: assert response.status_code == status return response - def _check_ok(self, response): + def _check_ok(self, response, org=None, member=False): content = response.render().content.decode('utf-8') context = RequestContext(self.request) - context['object'] = self.org + context['object'] = org or self.org + if member: + context['projects'] = Project.objects.filter( + organization__slug=self.org.slug) + elif org is None: + context['projects'] = Project.objects.filter( + organization__slug=self.org.slug, access='public') + expected = render_to_string( 'organization/organization_dashboard.html', context @@ -182,6 +197,17 @@ def test_get_with_unauthorized_user(self): response = self._get(self.org.slug, status=200) self._check_ok(response) + def test_get_with_org_membership(self): + response = self._get( + self.org.slug, status=200, make_org_member=self.org) + self._check_ok(response, member=True) + + def test_get_with_new_org(self): + new_org = OrganizationFactory.create() + assign_user_policies(self.user, self.policy) + response = self._get(new_org.slug, status=200) + self._check_ok(response, org=new_org) + class OrganizationEditTest(TestCase): def setUp(self): diff --git a/cadasta/organization/views/default.py b/cadasta/organization/views/default.py index f603efb1b..2e161ea34 100644 --- a/cadasta/organization/views/default.py +++ b/cadasta/organization/views/default.py @@ -54,6 +54,25 @@ class OrganizationDashboard(PermissionRequiredMixin, generic.DetailView): template_name = 'organization/organization_dashboard.html' permission_required = 'org.view' + def get_context_data(self, member=False, **kwargs): + context = super(OrganizationDashboard, self).get_context_data(**kwargs) + if member: + projects = self.object.all_projects() + else: + projects = self.object.public_projects() + context['projects'] = projects + return context + + def get(self, request, *args, **kwargs): + self.object = self.get_object() + context = self.get_context_data() + if hasattr(self.request.user, 'organizations'): + orgs = self.request.user.organizations.all() + for org in orgs: + if org.slug == self.kwargs['slug']: + context = self.get_context_data(member=True) + return super(generic.DetailView, self).render_to_response(context) + class OrganizationEdit(LoginPermissionRequiredMixin, generic.UpdateView): diff --git a/cadasta/templates/organization/organization_dashboard.html b/cadasta/templates/organization/organization_dashboard.html index 6fbef14c2..c9e2e7538 100644 --- a/cadasta/templates/organization/organization_dashboard.html +++ b/cadasta/templates/organization/organization_dashboard.html @@ -85,7 +85,7 @@
{{ prj.name }} | {{ prj.country }} | diff --git a/cadasta/templates/organization/organization_list.html b/cadasta/templates/organization/organization_list.html index a24a704a1..a72279676 100644 --- a/cadasta/templates/organization/organization_list.html +++ b/cadasta/templates/organization/organization_list.html @@ -42,7 +42,11 @@{{ org.projects.count }} | + {% if user.is_authenticated and org in user.organizations.all %} +{{ org.all_projects.count }} | + {% else %} +{{ org.public_projects.count }} | + {% endif %}