From 7324ded5f89839bc22bd7db890a15870e623d7a6 Mon Sep 17 00:00:00 2001 From: TeriForey Date: Fri, 21 Sep 2018 16:12:42 +0100 Subject: [PATCH 1/9] Made the changes according to PR eamena_v3/pull/32 --- arches/app/models/models.py | 1 + arches/app/models/resource.py | 23 +++ arches/app/utils/index_database.py | 1 + arches/app/utils/index_database_.py | 1 + arches/install/django_overrides/admin.py | 6 +- eamena/eamena/media/js/admin_group.js | 68 ++++++++ .../media/js/views/search/search-results.js | 3 +- eamena/eamena/models/group.py | 52 ++++++ eamena/eamena/models/resource.py | 3 +- .../admin/auth/group/change_form.html | 1 + eamena/eamena/templates/map.htm | 6 +- eamena/eamena/templates/search.htm | 2 +- .../eamena/templates/views/reports/title.htm | 4 +- .../templates/views/search/search-results.htm | 2 +- eamena/eamena/views/resources.py | 154 ++++++++++++++++++ eamena/eamena/views/search.py | 36 +++- 16 files changed, 352 insertions(+), 11 deletions(-) create mode 100644 eamena/eamena/media/js/admin_group.js create mode 100644 eamena/eamena/models/group.py diff --git a/arches/app/models/models.py b/arches/app/models/models.py index 1f4cf9698c..1f4a640c13 100644 --- a/arches/app/models/models.py +++ b/arches/app/models/models.py @@ -50,6 +50,7 @@ class AuthGroup(models.Model): id = models.IntegerField(primary_key=True) name = models.CharField(unique=True, max_length=80) + geom = models.GeometryField() class Meta: db_table = u'auth_group' diff --git a/arches/app/models/resource.py b/arches/app/models/resource.py index 53da4fa020..e4f521bf38 100644 --- a/arches/app/models/resource.py +++ b/arches/app/models/resource.py @@ -992,6 +992,29 @@ def prepare_term_index(self, create=False): return index_settings + def prepare_maplayer_index(self, create=False): + """ + Creates the mappings for the maplayers index + """ + index_settings = { + "mappings": { + "HERITAGE_RESOURCE_GROUP.E27": { + "properties": { + "geometry": { + "type": "geo_shape" + } + } + } + } + } + + if create: + se = SearchEngineFactory().create() + se.create_index(index='maplayers', body=index_settings, ignore=400) + + return index_settings + + def prepare_resource_relations_index(self, create=False): """ Creates the settings and mappings in Elasticsearch to support related resources diff --git a/arches/app/utils/index_database.py b/arches/app/utils/index_database.py index 3ae970fc20..85b67a45d4 100644 --- a/arches/app/utils/index_database.py +++ b/arches/app/utils/index_database.py @@ -42,6 +42,7 @@ def index_resources(): se.delete_index(index=index_type) se.delete(index='term', body='{"query":{"bool":{"must":[{"constant_score":{"filter":{"missing":{"field":"value.options.conceptid"}}}}],"must_not":[],"should":[]}}}') + Resource().prepare_maplayer_index(create=True) Resource().prepare_term_index(create=True) cursor = connection.cursor() diff --git a/arches/app/utils/index_database_.py b/arches/app/utils/index_database_.py index 9fc4563e43..27da43955d 100644 --- a/arches/app/utils/index_database_.py +++ b/arches/app/utils/index_database_.py @@ -42,6 +42,7 @@ def index_resources(): se.delete_index(index=index_type) se.delete(index='term', body='{"query":{"bool":{"must":[{"constant_score":{"filter":{"missing":{"field":"value.options.conceptid"}}}}],"must_not":[],"should":[]}}}') + Resource().prepare_maplayer_index(create=True) Resource().prepare_term_index(create=True) cursor = connection.cursor() diff --git a/arches/install/django_overrides/admin.py b/arches/install/django_overrides/admin.py index 7d9a4ec045..861fb6f9fc 100644 --- a/arches/install/django_overrides/admin.py +++ b/arches/install/django_overrides/admin.py @@ -15,15 +15,19 @@ from django.utils.translation import ugettext, ugettext_lazy as _ from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters +from eamena.eamena.models.group import EamenaAuthGroup +from django.contrib.gis.admin import GeoModelAdmin csrf_protect_m = method_decorator(csrf_protect) sensitive_post_parameters_m = method_decorator(sensitive_post_parameters()) -class GroupAdmin(admin.ModelAdmin): +class GroupAdmin(GeoModelAdmin): search_fields = ('name',) ordering = ('name',) filter_vertical = ('permissions',) + # openlayers_url = 'https://cdnjs.cloudflare.com/ajax/libs/openlayers/3.20.1/ol.js' + extra_js = ['js/admin_group.js'] def formfield_for_manytomany(self, db_field, request=None, **kwargs): if db_field.name == 'permissions': diff --git a/eamena/eamena/media/js/admin_group.js b/eamena/eamena/media/js/admin_group.js new file mode 100644 index 0000000000..cc81605feb --- /dev/null +++ b/eamena/eamena/media/js/admin_group.js @@ -0,0 +1,68 @@ +var WGS84 = new OpenLayers.Projection("EPSG:4326"); +var Mercator = new OpenLayers.Projection("EPSG:900913"); +//enable drag and drop of kml files onto django admin map view +django.jQuery( document ).ready(function() { + console.log( "ready!" ); + console.log('loaded'); + + var mapEl = django.jQuery('#id_geom_map')[0]; + + if(mapEl) { + mapEl.ondrop = function (evt) { + evt.stopPropagation(); + evt.preventDefault(); + if(evt.dataTransfer.files[0]) { + handleFile(evt.dataTransfer.files[0]); + } + }; + mapEl.ondragenter = function (evt) { + evt.stopPropagation(); + evt.preventDefault(); + }; + mapEl.ondragover = function (evt) { + evt.stopPropagation(); + evt.preventDefault(); + }; + } + + + var handleFile = function(file) { + + var reader = new FileReader(); + reader.onload = function (evt) { + if (evt.error) { + readerror(); + return; + } + + var results = null; + var content = evt.target.result; + var engine; + var formats = ['KML', 'GPX', 'OSM']; + for (var i = 0; i < formats.length; i++) { + engine = new OpenLayers.Format[formats[i]]({ + internalProjection: WGS84, + externalProjection: WGS84, + extractStyles: true + }); + try { + results = engine.read(content); + } catch (e) {} + if (results && results.length) { + break; + } + } + if (!results || !results.length) { + readerror(); + return; + } + + //geodjango_geom is a global var created by the geodjango admin view + geodjango_geom.clearFeatures() + geodjango_geom.layers.vector.addFeatures(results); + geodjango_geom.map.zoomToExtent(geodjango_geom.layers.vector.getDataExtent()); + }; + reader.readAsText(file); + }; + +}) \ No newline at end of file diff --git a/eamena/eamena/media/js/views/search/search-results.js b/eamena/eamena/media/js/views/search/search-results.js index 19a100357b..c3e3836a47 100644 --- a/eamena/eamena/media/js/views/search/search-results.js +++ b/eamena/eamena/media/js/views/search/search-results.js @@ -150,7 +150,8 @@ define(['jquery', description: description, geometries: ko.observableArray(this._source.geometries), typeIcon: resourceTypes[this._source.entitytypeid].icon, - typeName: resourceTypes[this._source.entitytypeid].name + typeName: resourceTypes[this._source.entitytypeid].name, + can_edit: this.can_edit }); }); return data; diff --git a/eamena/eamena/models/group.py b/eamena/eamena/models/group.py new file mode 100644 index 0000000000..601d96f0e5 --- /dev/null +++ b/eamena/eamena/models/group.py @@ -0,0 +1,52 @@ +from django.contrib.gis.db.models import GeometryField, GeoManager +from django.contrib.gis.geos import GEOSGeometry +from arches.app.search.search_engine_factory import SearchEngineFactory +from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer +from arches.app.search.elasticsearch_dsl_builder import Query, Terms, Bool, Match, Nested +from django.contrib.auth.models import Group + +if not hasattr(Group, 'area'): + geom = GeometryField() + geom.contribute_to_class(Group, 'geom') + objects = GeoManager() + + +class EamenaAuthGroup(Group): + class Meta: + proxy = True + + +def canUserAccessResource(user, resourceid, action='view'): + """ + Should the given user be allowed to access the resource in the way given by action + Access is determined by the user's membership of groups and the geometries associated to those groups + user: the django user + resourceid: the resource being accessed + action: either 'view', or 'edit' + """ + + # Get the geometry for resource + se = SearchEngineFactory().create() + report_info = se.search(index='resource', id=resourceid) + if not report_info: + return True + + geometry = JSONSerializer().serialize(report_info['_source']['geometry']) + + if geometry is 'null': + return True + + groups = user.groups + if action is 'edit': + groups = groups.filter(name__startswith="edit") + elif action is 'delete' or action is 'export': + groups = groups.filter(name__startswith="editplus") + site_geom = GEOSGeometry(geometry) + + for group in groups.all(): + if group.geom: + group_geom = GEOSGeometry(group.geom) + if group_geom.contains(site_geom): + return True; + + return False \ No newline at end of file diff --git a/eamena/eamena/models/resource.py b/eamena/eamena/models/resource.py index 3797fbe16a..ecbeb099d3 100644 --- a/eamena/eamena/models/resource.py +++ b/eamena/eamena/models/resource.py @@ -148,7 +148,8 @@ def __init__(self, *args, **kwargs): 'name': _('Manage Resource'), 'forms': [ forms.EditHistory.get_info(), - forms.DeleteResourceForm.get_info() + # this is now added in the view if the user has appropriate permissions + # forms.DeleteResourceForm.get_info() ] }) diff --git a/eamena/eamena/templates/admin/auth/group/change_form.html b/eamena/eamena/templates/admin/auth/group/change_form.html index 308eccad44..6e88f0dcbc 100644 --- a/eamena/eamena/templates/admin/auth/group/change_form.html +++ b/eamena/eamena/templates/admin/auth/group/change_form.html @@ -5,6 +5,7 @@ {% trans "History" %}
  • + My Link {% trans 'Group activity' %}
  • {% endblock %} \ No newline at end of file diff --git a/eamena/eamena/templates/map.htm b/eamena/eamena/templates/map.htm index f6cdf75647..4576e7056e 100644 --- a/eamena/eamena/templates/map.htm +++ b/eamena/eamena/templates/map.htm @@ -316,9 +316,9 @@