Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arches/app/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down
23 changes: 23 additions & 0 deletions arches/app/models/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions arches/app/utils/index_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
1 change: 1 addition & 0 deletions arches/app/utils/index_database_.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 1 addition & 2 deletions arches/app/utils/set_anonymous_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ def process_request(self, request):
request.user = User.objects.get(username='anonymous')
except:
pass

request.user.user_groups = [group.name for group in request.user.groups.all()]
request.user.user_groups = ", ".join([group.name for group in request.user.groups.all()])
7 changes: 4 additions & 3 deletions arches/app/views/concept.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from django.views.decorators.csrf import csrf_exempt
from django.template import RequestContext
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.decorators import user_passes_test
from arches.app.models import models
from arches.app.models.concept import Concept, ConceptValue, CORE_CONCEPTS
from arches.app.search.search_engine_factory import SearchEngineFactory
Expand All @@ -33,14 +33,15 @@
from arches.app.utils.JSONResponse import JSONResponse
from arches.app.utils.skos import SKOSWriter, SKOSReader
from django.utils.module_loading import import_by_path
from eamena.models.group import edit_group_check


sparql_providers = {}
for provider in settings.SPARQL_ENDPOINT_PROVIDERS:
Provider = import_by_path(provider)()
sparql_providers[Provider.endpoint] = Provider

@permission_required('edit')
@user_passes_test(edit_group_check)
def rdm(request, conceptid):
lang = request.GET.get('lang', request.LANGUAGE_CODE)
languages = models.DLanguages.objects.all()
Expand All @@ -60,7 +61,7 @@ def rdm(request, conceptid):



@permission_required('edit')
@user_passes_test(edit_group_check)
@csrf_exempt
def concept(request, conceptid):
f = request.GET.get('f', 'json')
Expand Down
68 changes: 64 additions & 4 deletions arches/app/views/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,33 @@
from django.template import RequestContext
from django.shortcuts import render_to_response, redirect
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import permission_required
from django.conf import settings
from django.db import transaction
from arches.app.models import models
from arches.app.models.resource import Resource
from arches.app.utils.betterJSONSerializer import JSONSerializer, JSONDeserializer
from arches.app.utils.JSONResponse import JSONResponse
from arches.app.search.search_engine_factory import SearchEngineFactory
from arches.app.search.elasticsearch_dsl_builder import Query, Terms
from arches.app.search.elasticsearch_dsl_builder import Query, Terms, Bool, GeoShape
from arches.app.views.concept import get_preflabel_from_valueid
from arches.app.models.concept import Concept
from django.http import HttpResponseNotFound
from django.contrib.gis.geos import GEOSGeometry
from django.db.models import Max, Min
from django.contrib.auth.decorators import user_passes_test
from eamena.models import forms
from eamena.models.group import canUserAccessResource, edit_group_check, canUserCreateResource
from django.core.exceptions import PermissionDenied

def report(request, resourceid):
raise NotImplementedError('Reports are not yet implemented.')

@permission_required('edit')
@user_passes_test(edit_group_check)
@csrf_exempt
def resource_manager(request, resourcetypeid='', form_id='default', resourceid=''):
can_edit = canUserAccessResource(request.user, resourceid, 'edit');
if not can_edit:
raise PermissionDenied

if resourceid != '':
resource = Resource(resourceid)
Expand All @@ -51,9 +56,18 @@ def resource_manager(request, resourcetypeid='', form_id='default', resourceid='
if form_id == 'default':
form_id = resource.form_groups[0]['forms'][0]['id']

if canUserAccessResource(request.user, resourceid, 'delete'):
# add the delete form
manage_groups = [x for x in resource.form_groups if x['id'] == 'manage-resource']
if len(manage_groups) > 0:
manage_group = manage_groups[0]
manage_group['forms'].append(forms.DeleteResourceForm.get_info())

form = resource.get_form(form_id)

if request.method == 'DELETE':
if not canUserAccessResource(request.user, resourceid, 'delete'):
raise PermissionDenied
resource.delete_index()
se = SearchEngineFactory().create()
realtionships = resource.get_related_resources(return_entities=False)
Expand All @@ -68,6 +82,10 @@ def resource_manager(request, resourcetypeid='', form_id='default', resourceid='
form.set_user(request.user)
form.update(data, request.FILES)

# Before saving the resource, need to check the location is within the group boundary (Can't use SE for this)
if not canUserCreateResource(request.user, resource):
raise PermissionDenied

with transaction.atomic():
if resourceid != '':
resource.delete_index()
Expand Down Expand Up @@ -175,12 +193,44 @@ def map_layers(request, entitytypeid='all', get_centroids=False):
se = SearchEngineFactory().create()
query = Query(se, limit=limit)

boolfilter = Bool()

# filter based on user's group geometries
locationfilter = Bool()
for group in request.user.groups.all():
if group.name.startswith('restrict'):
continue
if group.geom:
geojson = group.geom.geojson
geojson_as_dict = JSONDeserializer().deserialize(geojson)
geoshape = GeoShape(field='geometry', type=geojson_as_dict['type'],
coordinates=geojson_as_dict['coordinates'])
locationfilter.should(geoshape)
boolfilter.must(locationfilter)

if request.user.groups.filter(name__startswith='restrict').all():
restrictedfilter = Bool()
for restrictedGroup in request.user.groups.filter(name__startswith='restrict').all():
if restrictedGroup.geom:
geojson = restrictedGroup.geom.geojson
geojson_as_dict = JSONDeserializer().deserialize(geojson)
geoshape = GeoShape(field='geometry', type=geojson_as_dict['type'],
coordinates=geojson_as_dict['coordinates'])
restrictedfilter.should(geoshape)
boolfilter.must_not(restrictedfilter)

query.add_query(boolfilter)

args = { 'index': 'maplayers' }
if entitytypeid != 'all':
args['doc_type'] = entitytypeid
if entityids != '':
for entityid in entityids.split(','):
geojson_collection['features'].append(se.search(index='maplayers', id=entityid)['_source'])
record = se.search(index='maplayers', id=entityid)['_source']
# Set a param to indicate the user's permissions for this resource
record['properties']['can_edit'] = canUserAccessResource(request.user, record['id'], 'edit')

geojson_collection['features'].append(record)
return JSONResponse(geojson_collection)


Expand Down Expand Up @@ -212,9 +262,19 @@ def map_layers(request, entitytypeid='all', get_centroids=False):
item['_source']['geometry'] = item['_source']['properties'][geom_param]
item['_source']['properties'].pop('extent', None)
item['_source']['properties'].pop(geom_param, None)

# Set a param to indicate the user's permissions for this resource
# This may be expensive, but we are assuming there won't be large numbers of results here
can_edit = canUserAccessResource(request.user, item['_source']['id'], 'edit')
item['_source']['properties']['can_edit'] = can_edit
else:
item['_source']['properties'].pop('extent', None)
item['_source']['properties'].pop('centroid', None)

# Set a param to indicate the user's permissions for this resource
# This may be expensive, but we are assuming there won't be large numbers of results here
can_edit = canUserAccessResource(request.user, item['_source']['id'], 'edit')
item['_source']['properties']['can_edit'] = can_edit
geojson_collection['features'].append(item['_source'])

return JSONResponse(geojson_collection)
Expand Down
36 changes: 35 additions & 1 deletion arches/install/django_overrides/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,35 @@
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 olwidget.admin import GeoModelAdmin
from django import forms
from olwidget.fields import MapField, EditableLayerField

csrf_protect_m = method_decorator(csrf_protect)
sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())


class GroupAdmin(admin.ModelAdmin):
class GroupAdminForm(forms.ModelForm):
geom = MapField([
EditableLayerField({'geometry': 'polygon', 'name': 'geom', 'isCollection': True}),
], {
'layers': ['bing.AerialWithLabels', 'bing.Aerial', 'osm.mapnik'],
'default_lat': 29,
'default_lon': 15,
}, template="olwidget/admin_olwidget.html")

def clean(self):
self.cleaned_data['geom'] = self.cleaned_data['geom'][0]
return self.cleaned_data

class Meta:
model = Group


class GroupAdmin(GeoModelAdmin):

form = GroupAdminForm

search_fields = ('name',)
ordering = ('name',)
filter_vertical = ('permissions',)
Expand All @@ -35,6 +58,17 @@ def formfield_for_manytomany(self, db_field, request=None, **kwargs):
db_field, request=request, **kwargs)


def add_view(self, request, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['bingkey'] = settings.BING_KEY
return super(GroupAdmin, self).add_view(request, form_url, extra_context=extra_context)

def change_view(self, request, object_id, form_url='', extra_context=None):
extra_context = extra_context or {}
extra_context['bingkey'] = settings.BING_KEY
return super(GroupAdmin, self).change_view(request, object_id, form_url, extra_context=extra_context)


class UserAdmin(admin.ModelAdmin):
add_form_template = 'admin/auth/user/add_form.html'
change_user_password_template = None
Expand Down
102 changes: 102 additions & 0 deletions eamena/eamena/media/js/admin_group.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
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!");

var mapEl = django.jQuery('#id_geom')[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 allfeatures = [];

var existingfeatures = olwidget_id_geom.vectorLayers[0].features;
for (var i =0; i < existingfeatures.length; i++){
if (existingfeatures[i].geometry) {
existingfeatures[i].geometry.transform(Mercator, WGS84);
allfeatures.push(existingfeatures[i]);
}
}


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;
}

for (var i = 0; i < results.length; i++){
if (results[i].geometry.components) {
allfeatures.push(results[i]);
}
}


var options = {
'internalProjection': new OpenLayers.Projection("EPSG:4326"),
'externalProjection': new OpenLayers.Projection("EPSG:4326")
};
var wktFormat = new OpenLayers.Format.WKT(options);
var wkttext = wktFormat.write(allfeatures);

for (var i =0; i < olwidget_id_geom.layers.length; i++){
if (olwidget_id_geom.layers[i].CLASS_NAME == "olwidget.EditableLayer"){
var mylayr = olwidget_id_geom.layers[i];
mylayr.clearFeatures();
if (mylayr.textarea.value.length > 0) {
mylayr.textarea.value = mylayr.textarea.value + ',' + wkttext;
}else{
mylayr.textarea.value = wkttext;
}
mylayr.readWKT();
}
}
olwidget_id_geom.initCenter();

};
reader.readAsText(file);
};

})
3 changes: 2 additions & 1 deletion eamena/eamena/media/js/views/search/search-results.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading