def test_apply_provisional_edit(self): """ Tests that provisional edit data is properly created """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": "", "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" }, } user = User.objects.create_user(username="******", password="******") provisional_tile = Tile(json) request = HttpRequest() request.user = user provisional_tile.save(index=False, request=request) provisional_tile.apply_provisional_edit(user, {"test": "test"}, "update") provisionaledits = provisional_tile.provisionaledits userid = str(user.id) self.assertEqual(provisionaledits[userid]["action"], "update") self.assertEqual(provisionaledits[userid]["reviewer"], None) self.assertEqual(provisionaledits[userid]["value"], {"test": "test"}) self.assertEqual(provisionaledits[userid]["status"], "review") self.assertEqual(provisionaledits[userid]["reviewtimestamp"], None)
def test_apply_provisional_edit(self): """ Tests that provisional edit data is properly created """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } user = User.objects.create_user(username='******', password='******') provisional_tile = Tile(json) request = HttpRequest() request.user = user provisional_tile.save(index=False, request=request) provisional_tile.apply_provisional_edit(user, {"test":"test"}, 'update') provisionaledits = JSONDeserializer().deserialize(provisional_tile.provisionaledits) userid = str(user.id) self.assertEqual(provisionaledits[userid]['action'], 'update') self.assertEqual(provisionaledits[userid]['reviewer'], None) self.assertEqual(provisionaledits[userid]['value'], {"test":"test"}) self.assertEqual(provisionaledits[userid]['status'], "review") self.assertEqual(provisionaledits[userid]['reviewtimestamp'], None)
def test_save(self): """ Test that we can save a Tile object back to the database """ login = self.client.login(username='******', password='******') json = { "tiles": { "72048cb3-adbc-11e6-9ccf-14109fd34195": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } }] }, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "7204869c-adbc-11e6-8bec-14109fd34195", "tileid": "", "data": {} } t = Tile(json) t.save(index=False) tiles = Tile.objects.filter(resourceinstance_id="40000000-0000-0000-0000-000000000000") self.assertEqual(tiles.count(), 2)
def test_tile_cardinality(self): """ Tests that the tile is not saved if the cardinality is violated by testin to save a tile with the same values as existing one """ self.user = User.objects.get(username="******") first_json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": "", "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" }, } first_tile = Tile(first_json) request = HttpRequest() request.user = self.user first_tile.save(index=False, request=request) second_json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": "", "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" }, } second_tile = Tile(second_json) with self.assertRaises(TileCardinalityError): second_tile.save(index=False, request=request)
def test_tile_deletion(self): """ Tests that a tile is deleted when a user is a reviewer or owner. """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } owner = User.objects.create_user(username='******', password='******') reviewer = User.objects.get(username='******') tile1 = Tile(json) owner_request = HttpRequest() owner_request.user = owner tile1.save(index=False, request=owner_request) tile1.delete(request=owner_request) tile2 = Tile(json) reviewer_request = HttpRequest() reviewer_request.user = reviewer tile2.save(index=False, request=reviewer_request) tile2.delete(request=reviewer_request) self.assertEqual(len(Tile.objects.all()), 0)
def test_provisional_deletion(self): """ Tests that a tile is NOT deleted if a user does not have the privlages to delete a tile and that the proper provisionaledit is applied. """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } provisional_user = User.objects.create_user(username='******', password='******') reviewer = User.objects.get(username='******') tile = Tile(json) reviewer_request = HttpRequest() reviewer_request.user = reviewer tile.save(index=False, request=reviewer_request) provisional_request = HttpRequest() provisional_request.user = provisional_user tile.delete(request=provisional_request) self.assertEqual(len(Tile.objects.all()), 1)
def test_create_new_provisional(self): """ Test that a new provisional tile is created when a user IS NOT a reviwer. """ self.user = User.objects.create_user(username="******", password="******") json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": "", "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "PROVISIONAL" }, } provisional_tile = Tile(json) request = HttpRequest() request.user = self.user provisional_tile.save(index=False, request=request) self.assertEqual(provisional_tile.is_provisional(), True)
def test_simple_get(self): """ Test that we can get a Tile object """ json = { "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "20000000-0000-0000-0000-000000000001", "tileid": "", "data": { "20000000-0000-0000-0000-000000000004": "TEST 1" } } t = Tile(json) t.save() t2 = Tile.get(tileid=t.tileid) self.assertEqual(t.tileid, t2.tileid) self.assertEqual(t2.data["20000000-0000-0000-0000-000000000004"], "TEST 1")
def test_apply_provisional_edit(self): """ Tests that provisional edit data is properly created """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } user = User.objects.create_user(username='******', password='******') provisional_tile = Tile(json) request = HttpRequest() request.user = user provisional_tile.save(index=False, request=request) provisional_tile.apply_provisional_edit(user, {"test": "test"}, 'update') provisionaledits = JSONDeserializer().deserialize( provisional_tile.provisionaledits) userid = str(user.id) self.assertEqual(provisionaledits[userid]['action'], 'update') self.assertEqual(provisionaledits[userid]['reviewer'], None) self.assertEqual(provisionaledits[userid]['value'], {"test": "test"}) self.assertEqual(provisionaledits[userid]['status'], "review") self.assertEqual(provisionaledits[userid]['reviewtimestamp'], None)
def test_provisional_deletion(self): """ Tests that a tile is NOT deleted if a user does not have the privlages to delete a tile and that the proper provisionaledit is applied. """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } provisional_user = User.objects.create_user( username='******', password='******') reviewer = User.objects.get(username='******') tile = Tile(json) reviewer_request = HttpRequest() reviewer_request.user = reviewer tile.save(index=False, request=reviewer_request) provisional_request = HttpRequest() provisional_request.user = provisional_user tile.delete(request=provisional_request) self.assertEqual(len(Tile.objects.all()), 1)
def test_save_provisional_from_athoritative(self): """ Test that a provisional edit is created when a user that is not a reviewer edits an athoritative tile """ json = { "tiles": [{ "tiles": [], "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" } }], "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "7204869c-adbc-11e6-8bec-14109fd34195", "tileid": "", "data": {} } t = Tile(json) t.save(index=False) self.user = User.objects.create_user(username='******', password='******') login = self.client.login(username='******', password='******') tiles = Tile.objects.filter( resourceinstance_id="40000000-0000-0000-0000-000000000000") provisional_tile = None for tile in tiles: provisional_tile = tile provisional_tile.data[ "72048cb3-adbc-11e6-9ccf-14109fd34195"] = 'PROVISIONAL' request = HttpRequest() request.user = self.user provisional_tile.save(index=False, request=request) tiles = Tile.objects.filter( resourceinstance_id="40000000-0000-0000-0000-000000000000") provisionaledits = provisional_tile.provisionaledits self.assertEqual(tiles.count(), 2) self.assertEqual( provisional_tile.data["72048cb3-adbc-11e6-9ccf-14109fd34195"], 'AUTHORITATIVE') self.assertEqual(provisionaledits[str(self.user.id)]['action'], 'update') self.assertEqual(provisionaledits[str(self.user.id)]['status'], 'review')
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) if json != None: data = JSONDeserializer().deserialize(json) tile_id = data['tileid'] if tile_id != None and tile_id != '': old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: tile.save(request=request) except ValidationError as e: return JSONResponse( { 'status': 'false', 'message': e.args }, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse( { 'status': 'false', 'message': [_('Request Failed'), _('Permission Denied')] }, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) return HttpResponseNotFound()
def test_save(self): """ Test that we can save a Tile object back to the database """ json = { "tiles": { "19999999-0000-0000-0000-000000000000": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "19999999-0000-0000-0000-000000000000", "tileid": "", "data": { "20000000-0000-0000-0000-000000000004": "TEST 1", "20000000-0000-0000-0000-000000000002": "TEST 2", "20000000-0000-0000-0000-000000000003": "TEST 3" } }], "32999999-0000-0000-0000-000000000000": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "32999999-0000-0000-0000-000000000000", "tileid": "", "data": { "20000000-0000-0000-0000-000000000004": "TEST 4", "20000000-0000-0000-0000-000000000002": "TEST 5", } }] }, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "20000000-0000-0000-0000-000000000001", "tileid": "", "data": {} } t = Tile(json) t.save() tiles = models.Tile.objects.filter( resourceinstance_id="40000000-0000-0000-0000-000000000000") self.assertEqual(tiles.count(), 3)
def push_edits_to_db(self): # read all docs that have changes # save back to postgres db db = self.couch.create_db('project_' + str(self.id)) ret = [] for row in db.view('_all_docs', include_docs=True): ret.append(row) if 'tileid' in row.doc: tile = Tile(row.doc) #if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): tile.save() #tile = models.TileModel.objects.get(pk=row.doc.tileid).update(**row.doc) return ret
def push_edits_to_db(self): # read all docs that have changes # save back to postgres db db = self.couch['project_' + str(self.id)] ret = [] for row in db.view('_all_docs', include_docs=True): ret.append(row) if 'tileid' in row.doc: tile = Tile(row.doc) #if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): tile.save() #tile = models.TileModel.objects.get(pk=row.doc.tileid).update(**row.doc) return ret
def test_save_provisional_from_athoritative(self): """ Test that a provisional edit is created when a user that is not a reviewer edits an athoritative tile """ json = { "tiles": { "72048cb3-adbc-11e6-9ccf-14109fd34195": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" } }] }, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "7204869c-adbc-11e6-8bec-14109fd34195", "tileid": "", "data": {} } t = Tile(json) t.save(index=False) self.user = User.objects.create_user(username='******', password='******') login = self.client.login(username='******', password='******') tiles = Tile.objects.filter(resourceinstance_id="40000000-0000-0000-0000-000000000000") provisional_tile = None for tile in tiles: if "72048cb3-adbc-11e6-9ccf-14109fd34195" in tile.data: provisional_tile = tile provisional_tile.data["72048cb3-adbc-11e6-9ccf-14109fd34195"] = 'PROVISIONAL' request = HttpRequest() request.user = self.user provisional_tile.save(index=False, request=request) tiles = Tile.objects.filter(resourceinstance_id="40000000-0000-0000-0000-000000000000") provisionaledits = JSONDeserializer().deserialize(provisional_tile.provisionaledits) self.assertEqual(tiles.count(), 2) self.assertEqual(provisional_tile.data["72048cb3-adbc-11e6-9ccf-14109fd34195"], 'AUTHORITATIVE') self.assertEqual(provisionaledits[str(self.user.id)]['action'], 'update') self.assertEqual(provisionaledits[str(self.user.id)]['status'], 'review')
def test_save(self): """ Test that we can save a Tile object back to the database """ json = { "tiles": { "19999999-0000-0000-0000-000000000000": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "19999999-0000-0000-0000-000000000000", "tileid": "", "data": { "20000000-0000-0000-0000-000000000004": "TEST 1", "20000000-0000-0000-0000-000000000002": "TEST 2", "20000000-0000-0000-0000-000000000003": "TEST 3" } }], "32999999-0000-0000-0000-000000000000": [{ "tiles": {}, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "32999999-0000-0000-0000-000000000000", "tileid": "", "data": { "20000000-0000-0000-0000-000000000004": "TEST 4", "20000000-0000-0000-0000-000000000002": "TEST 5", } }] }, "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "20000000-0000-0000-0000-000000000001", "tileid": "", "data": {} } t = Tile(json) t.save() tiles = models.Tile.objects.filter(resourceinstance_id="40000000-0000-0000-0000-000000000000") self.assertEqual(tiles.count(), 3)
def test_create_new_provisional(self): """ Test that a new provisional tile is created when a user IS NOT a reviwer and that an authoritative tile is created when a user IS a reviwer. """ self.user = User.objects.get(username='******') json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" } } authoritative_tile = Tile(json) request = HttpRequest() request.user = self.user authoritative_tile.save(index=False, request=request) self.user = User.objects.create_user(username='******', password='******') json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "PROVISIONAL" } } provisional_tile = Tile(json) request = HttpRequest() request.user = self.user provisional_tile.save(index=False, request=request) self.assertEqual(provisional_tile.is_provisional(), True) self.assertEqual(authoritative_tile.is_provisional(), False)
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) if json != None: data = JSONDeserializer().deserialize(json) tile_id = data['tileid'] if tile_id != None and tile_id != '': old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: tile.save(request=request) except ValidationError as e: return JSONResponse({'status':'false','message':e.args}, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse({'status':'false','message': [_('Request Failed'), _('Permission Denied')]}, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) return HttpResponseNotFound()
def test_simple_get(self): """ Test that we can get a Tile object """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } t = Tile(json) t.save(index=False) t2 = Tile.objects.get(tileid=t.tileid) self.assertEqual(t.tileid, t2.tileid) self.assertEqual(t2.data["72048cb3-adbc-11e6-9ccf-14109fd34195"], "TEST 1")
def test_user_owns_provisional(self): """ Tests that a user is the owner of a provisional edit """ json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": '', "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "TEST 1" } } user = User.objects.create_user(username='******', password='******') provisional_tile = Tile(json) request = HttpRequest() request.user = user provisional_tile.save(index=False, request=request) self.assertEqual(provisional_tile.user_owns_provisional(user), True)
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) if json != None: data = JSONDeserializer().deserialize(json) tile = Tile(data) with transaction.atomic(): try: tile.save(request=request) except ValidationError as e: return JSONResponse( { 'status': 'false', 'message': e.args }, status=500) return JSONResponse(tile) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) return HttpResponseNotFound()
def test_create_new_authoritative(self): """ Test that a new authoritative tile is created when a user IS a reviwer. """ self.user = User.objects.get(username="******") json = { "resourceinstance_id": "40000000-0000-0000-0000-000000000000", "parenttile_id": "", "nodegroup_id": "72048cb3-adbc-11e6-9ccf-14109fd34195", "tileid": "", "data": { "72048cb3-adbc-11e6-9ccf-14109fd34195": "AUTHORITATIVE" }, } authoritative_tile = Tile(json) request = HttpRequest() request.user = self.user authoritative_tile.save(index=False, request=request) self.assertEqual(authoritative_tile.is_provisional(), False)
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) accepted_provisional = request.POST.get('accepted_provisional', None) if accepted_provisional != None: accepted_provisional_edit = JSONDeserializer().deserialize( accepted_provisional) if json != None: data = JSONDeserializer().deserialize(json) if data['resourceinstance_id'] == '': data['resourceinstance_id'] = uuid.uuid4() try: models.ResourceInstance.objects.get( pk=data['resourceinstance_id']) except ObjectDoesNotExist: resource = Resource() graphid = models.Node.objects.filter( nodegroup=data['nodegroup_id'])[0].graph_id resource.graph_id = graphid resource.save(user=request.user) data['resourceinstance_id'] = resource.pk resource.index() tile_id = data['tileid'] if tile_id != None and tile_id != '': old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: if accepted_provisional == None: tile.save(request=request) else: if accepted_provisional is not None: provisional_editor = User.objects.get( pk=accepted_provisional_edit["user"]) tile.save( provisional_edit_log_details={ "user": request.user, "action": "accept edit", "edit": accepted_provisional_edit, "provisional_editor": provisional_editor }) if tile_id == '4345f530-aa90-48cf-b4b3-92d1185ca439': import couchdb import json as json_json couch = couchdb.Server(settings.COUCHDB_URL) for project in models.MobileSurveyModel.objects.all( ): db = couch['project_' + str(project.id)] #tile = models.TileModel.objects.get(pk='4345f530-aa90-48cf-b4b3-92d1185ca439') tile_json = json_json.loads( JSONSerializer().serialize(tile)) tile_json['_id'] = tile_json['tileid'] for row in db.view('_all_docs', include_docs=True): if 'tileid' in row.doc and tile_json[ '_id'] == row.doc['_id']: tile_json['_rev'] = row.doc['_rev'] db.save(tile_json) if tile.provisionaledits is not None and str( request.user.id) in tile.provisionaledits: tile.data = tile.provisionaledits[str( request.user.id)]['value'] except ValidationError as e: return JSONResponse( { 'status': 'false', 'message': e.args }, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse( { 'status': 'false', 'message': [_('Request Failed'), _('Permission Denied')] }, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == 'delete_provisional_tile': user = request.POST.get('user', None) tileid = request.POST.get('tileid', None) users = request.POST.get('users', None) tile = Tile.objects.get(tileid=tileid) is_provisional = tile.is_provisional() if tileid is not None and user is not None: provisionaledits = self.delete_provisional_edit( tile, user, reviewer=request.user) elif tileid is not None and users is not None: users = jsonparser.loads(users) for user in users: self.delete_provisional_edit(tile, user, reviewer=request.user) if is_provisional == True: return JSONResponse({'result': 'delete'}) else: return JSONResponse({'result': 'success'}) return HttpResponseNotFound()
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) accepted_provisional = request.POST.get('accepted_provisional', None) if accepted_provisional is not None: accepted_provisional_edit = JSONDeserializer().deserialize( accepted_provisional) if json is not None: data = JSONDeserializer().deserialize(json) data[ 'resourceinstance_id'] = '' if 'resourceinstance_id' not in data else data[ 'resourceinstance_id'] if data['resourceinstance_id'] == '': data['resourceinstance_id'] = uuid.uuid4() try: models.ResourceInstance.objects.get( pk=data['resourceinstance_id']) except ObjectDoesNotExist: resource = Resource() graphid = models.Node.objects.filter( nodegroup=data['nodegroup_id'])[0].graph_id resource.graph_id = graphid try: resource.save(user=request.user) data['resourceinstance_id'] = resource.pk resource.index() except ModelInactiveError as e: message = _( 'Unable to save. Please verify the model status is active' ) return JSONResponse( { 'status': 'false', 'message': [_(e.title), _(str(message))] }, status=500) tile_id = data['tileid'] resource_instance = models.ResourceInstance.objects.get( pk=data['resourceinstance_id']) is_active = resource_instance.graph.isactive if tile_id is not None and tile_id != '': try: old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) except ObjectDoesNotExist as e: return self.handle_save_error( e, _('This tile is no longer available'), _('It was likely deleted by another user')) tile = Tile(data) if tile.filter_by_perm( request.user, 'write_nodegroup') and is_active is True: try: with transaction.atomic(): try: if accepted_provisional is None: try: tile.save(request=request) except TileValidationError as e: resource_tiles = models.TileModel.objects.filter( resourceinstance=tile. resourceinstance) if resource_tiles.count() == 0: Resource.objects.get( pk=tile.resourceinstance_id ).delete(request.user) title = _( 'Unable to save. Please verify your input is valid' ) return self.handle_save_error( e, tile_id, title=title) except ModelInactiveError as e: message = _( 'Unable to save. Please verify the model status is active' ) return JSONResponse( { 'status': 'false', 'message': [_(e.title), _(str(message))] }, status=500) else: if accepted_provisional is not None: provisional_editor = User.objects.get( pk=accepted_provisional_edit[ "user"]) prov_edit_log_details = { "user": request.user, "action": "accept edit", "edit": accepted_provisional_edit, "provisional_editor": provisional_editor } tile.save(request=request, provisional_edit_log_details= prov_edit_log_details) if tile.provisionaledits is not None and str( request.user.id ) in tile.provisionaledits: tile.data = tile.provisionaledits[str( request.user.id)]['value'] except Exception as e: return self.handle_save_error(e, tile_id) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) except Exception as e: return self.handle_save_error(e, tile_id) return JSONResponse(tile) elif is_active is False: response = { 'status': 'false', 'message': [ _('Request Failed'), _('Unable to Save. Verify model status is active') ] } return JSONResponse(response, status=500) else: response = { 'status': 'false', 'message': [_('Request Failed'), _('Permission Denied')] } return JSONResponse(response, status=500) if self.action == 'reorder_tiles': json = request.body if json is not None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == 'delete_provisional_tile': user = request.POST.get('user', None) tileid = request.POST.get('tileid', None) users = request.POST.get('users', None) tile = Tile.objects.get(tileid=tileid) is_provisional = tile.is_provisional() if tileid is not None and user is not None: provisionaledits = self.delete_provisional_edit( tile, user, request) elif tileid is not None and users is not None: users = jsonparser.loads(users) for user in users: self.delete_provisional_edit(tile, user, request) if is_provisional == True: return JSONResponse({'result': 'delete'}) else: return JSONResponse({'result': 'success'}) return HttpResponseNotFound()
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) if json != None: data = JSONDeserializer().deserialize(json) try: models.ResourceInstance.objects.get(pk=data['resourceinstance_id']) except ObjectDoesNotExist: resource = Resource() resource.resourceinstanceid = data['resourceinstance_id'] graphid = models.Node.objects.filter(nodegroup=data['nodegroup_id'])[0].graph_id resource.graph_id = graphid resource.save(user=request.user) resource.index() tile_id = data['tileid'] if tile_id != None and tile_id != '': old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: tile.save(request=request) if tile_id == '4345f530-aa90-48cf-b4b3-92d1185ca439': import couchdb import json as json_json couch = couchdb.Server(settings.COUCHDB_URL) for project in models.MobileSurveyModel.objects.all(): db = couch['project_' + str(project.id)] #tile = models.TileModel.objects.get(pk='4345f530-aa90-48cf-b4b3-92d1185ca439') tile_json = json_json.loads(JSONSerializer().serialize(tile)) tile_json['_id'] = tile_json['tileid'] for row in db.view('_all_docs', include_docs=True): if 'tileid' in row.doc and tile_json['_id'] == row.doc['_id']: tile_json['_rev'] = row.doc['_rev'] db.save(tile_json) except ValidationError as e: return JSONResponse({'status':'false','message':e.args}, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse({'status':'false','message': [_('Request Failed'), _('Permission Denied')]}, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == 'delete_provisional_tile': data = request.POST if 'tileid' in data: provisionaledits = self.delete_provisional_edit(data, request) return JSONResponse(provisionaledits) else: payload = data.get('payload', None) if payload is not None: edits = jsonparser.loads(payload) for edit in edits['edits']: provisionaledits = self.delete_provisional_edit(edit, request) return JSONResponse({'result':'success'}) return HttpResponseNotFound()
def push_edits_to_db(self, synclog=None): # read all docs that have changes # save back to postgres db db = self.couch.create_db('project_' + str(self.id)) user_lookup = {} is_reviewer = False with transaction.atomic(): couch_docs = self.couch.all_docs(db) for row in couch_docs: if row.doc['type'] == 'resource': if self.check_if_revision_exists(row.doc) is False: if 'provisional_resource' in row.doc and row.doc[ 'provisional_resource'] == 'true': resourceinstance, created = ResourceInstance.objects.update_or_create( resourceinstanceid=uuid.UUID( str(row.doc['resourceinstanceid'])), defaults={ 'graph_id': uuid.UUID(str(row.doc['graph_id'])) }) if created is True: self.save_revision_log(row.doc, synclog, 'create') else: self.save_revision_log(row.doc, synclog, 'update') print('Resource {0} Saved'.format( row.doc['resourceinstanceid'])) else: print('{0}: already saved'.format(row.doc['_rev'])) for row in couch_docs: if row.doc['type'] == 'tile' and \ ResourceInstance.objects.filter(pk=row.doc['resourceinstance_id']).exists(): if self.check_if_revision_exists(row.doc) is False: if 'provisionaledits' in row.doc and row.doc[ 'provisionaledits'] is not None: action = 'update' try: tile = Tile.objects.get( tileid=row.doc['tileid']) if row.doc['provisionaledits'] != '': for user_edits in row.doc[ 'provisionaledits'].items(): # user_edits is a tuple with the user number in # position 0, prov. edit data in position 1 for nodeid, value in iter( user_edits[1] ['value'].items()): datatype_factory = DataTypeFactory( ) node = models.Node.objects.get( nodeid=nodeid) datatype = datatype_factory.get_instance( node.datatype) newvalue = datatype.process_mobile_data( tile, node, db, row.doc, value) if newvalue is not None: user_edits[1]['value'][ nodeid] = newvalue if tile.provisionaledits is None: tile.provisionaledits = {} tile.provisionaledits[ user_edits[0]] = user_edits[1] self.handle_reviewer_edits( user_edits[0], tile) else: self.assign_provisional_edit( user_edits[0], user_edits[1], tile) # If there are conflicting documents, lets clear those out if '_conflicts' in row.doc: for conflict_rev in row.doc['_conflicts']: conflict_data = db.get( row.id, rev=conflict_rev) if conflict_data[ 'provisionaledits'] != '': for user_edits in conflict_data[ 'provisionaledits'].items( ): self.assign_provisional_edit( user_edits[0], user_edits[1], tile) # Remove conflicted revision from couch db.delete(conflict_data) except Tile.DoesNotExist: action = 'create' tile = Tile(row.doc) if row.doc['provisionaledits'] != '': for user_edits in row.doc[ 'provisionaledits'].items(): for nodeid, value in iter( user_edits[1] ['value'].items()): datatype_factory = DataTypeFactory( ) node = models.Node.objects.get( nodeid=nodeid) datatype = datatype_factory.get_instance( node.datatype) newvalue = datatype.process_mobile_data( tile, node, db, row.doc, value) if newvalue is not None: user_edits[1]['value'][ nodeid] = newvalue tile.provisionaledits[ user_edits[0]] = user_edits[1] self.handle_reviewer_edits( user_edits[0], tile) # If user is reviewer, apply as authoritative edit if tile.provisionaledits != '': for user_edits in tile.provisionaledits.items( ): if user_edits[0] not in user_lookup: user = User.objects.get( pk=user_edits[0]) user_lookup[user_edits[ 0]] = user.groups.filter( name='Resource Reviewer' ).exists() for user_id, is_reviewer in user_lookup.items( ): if is_reviewer: try: tile.data = tile.provisionaledits.pop( user_id)['value'] except KeyError: pass tile.save() self.save_revision_log(row.doc, synclog, action) print('Tile {0} Saved'.format(row.doc['tileid'])) db.compact()
def save_bngpoint(self, tile, request, is_function_save_method=True): """Finds the BNG Alphanumeric value for the centroid of the envelope(extent) of the Geometry, and saves that value to the bng_output_nodegroup of the tile. Args: self: GeoJSONToBNGPoint object. tile: Tile to attach / amend bng_output_nodegroup of. request: WSGI Request used to varify call is result of user action. N.B. Function Returns if empty. is_function_save_method: a bool stating whether the function calling it is the save function. """ # First let's check if this call is as a result of an inbound request (user action) or # as a result of the complementary BNGPointToGeoJSON function saving a new GeoJson. if request is None and is_function_save_method == True: return srid_LatLong = 4326 srid_BngAbs = 27700 # Reference grid for Easting/Northing to BNG Alphas. os_grid = { "09": "NA", "19": "NB", "29": "NC", "39": "ND", "49": "NE", "59": "OA", "69": "OB", "08": "NF", "18": "NG", "28": "NH", "38": "NJ", "48": "NK", "58": "OF", "68": "OG", "07": "NL", "17": "NM", "27": "NN", "37": "NO", "47": "NP", "57": "OL", "67": "OM", "06": "NQ", "16": "NR", "26": "NS", "36": "NT", "46": "NU", "56": "OQ", "66": "OR", "05": "NV", "15": "NW", "25": "NX", "35": "NY", "45": "NZ", "55": "OV", "65": "OW", "04": "SA", "14": "SB", "24": "SC", "34": "SD", "44": "SE", "54": "TA", "64": "TB", "03": "SF", "13": "SG", "23": "SH", "33": "SJ", "43": "SK", "53": "TF", "63": "TG", "02": "SL", "12": "SM", "22": "SN", "32": "SO", "42": "SP", "52": "TL", "62": "TM", "01": "SQ", "11": "SR", "21": "SS", "31": "ST", "41": "SU", "51": "TQ", "61": "TR", "00": "SV", "10": "SW", "20": "SX", "30": "SY", "40": "SZ", "50": "TV", "60": "TW", } geojsonnode = self.config["geojson_input_node"] bngnode = self.config["bng_output_node"] geojsonValue = tile.data[geojsonnode] if geojsonValue != None: # Grab a copy of the Geometry collection. geoJsFeatures = geojsonValue["features"] # Get the first feature as a GeosGeometry. geosGeom_union = GEOSGeometry(json.dumps(geoJsFeatures[0]["geometry"])) # update list. geoJsFeatures = geoJsFeatures[1:] # loop through list of geoJsFeatures. for item in geoJsFeatures: # .union seems to generate 'GEOS_ERROR: IllegalArgumentException:' # exceptions, but they seem spurious and are automatically ignored. geosGeom_union = geosGeom_union.union(GEOSGeometry(json.dumps(item["geometry"]))) # find the centroid of the envelope for the resultant Geometry Collection. centroidPoint = geosGeom_union.envelope.centroid # Explicitly declare the SRID for the current lat/long. centroidPoint = GEOSGeometry(centroidPoint, srid=srid_LatLong) # Transform to Absolute BNG. centroidPoint.transform(srid_BngAbs, False) # Get initial Easting and Northing digits. N.B. Left Zero pad integer coords to 6 digits! easting = str(int(centroidPoint.coords[0])).zfill(6) northing = str(int(centroidPoint.coords[1])).zfill(6) gridref = easting[0] + northing[0] # Get AlphaNumeric BNG try: gridref = os_grid[gridref] + easting[1:6] + northing[1:6] except KeyError: raise Exception("Conversion Error : Coordinates outside of BNG for England.") if self.config["bng_output_nodegroup"] == str(tile.nodegroup_id): tile.data[bngnode] = gridref else: previously_saved_tiles = Tile.objects.filter( nodegroup_id=self.config["bng_output_nodegroup"], resourceinstance_id=tile.resourceinstance_id ) # Update pre-existing tiles, or Create new one. if len(previously_saved_tiles) > 0: for p in previously_saved_tiles: p.data[bngnode] = gridref p.save() else: new_bng_tile = Tile().get_blank_tile_from_nodegroup_id( self.config["bng_output_nodegroup"], resourceid=tile.resourceinstance_id, parenttile=tile.parenttile ) new_bng_tile.data[bngnode] = gridref new_bng_tile.save() return return
def push_edits_to_db(self, synclog=None, userid=None): # read all docs that have changes # save back to postgres db db = self.couch.create_db('project_' + str(self.id)) user_lookup = {} is_reviewer = False sync_user = None sync_user_id = None if userid is not None: sync_user = User.objects.get(pk=userid) sync_user_id = str(sync_user.id) with transaction.atomic(): couch_docs = self.couch.all_docs(db) for row in couch_docs: if row.doc['type'] == 'resource': if self.check_if_revision_exists(row.doc) is False: if 'provisional_resource' in row.doc and row.doc[ 'provisional_resource'] == 'true': resourceinstance, created = ResourceInstance.objects.update_or_create( resourceinstanceid=uuid.UUID( str(row.doc['resourceinstanceid'])), defaults={ 'graph_id': uuid.UUID(str(row.doc['graph_id'])) }) if created is True: self.save_revision_log(row.doc, synclog, 'create') else: self.save_revision_log(row.doc, synclog, 'update') print('Resource {0} Saved'.format( row.doc['resourceinstanceid'])) else: print('{0}: already saved'.format(row.doc['_rev'])) for row in couch_docs: if row.doc['type'] == 'tile' and \ ResourceInstance.objects.filter(pk=row.doc['resourceinstance_id']).exists(): if self.check_if_revision_exists(row.doc) is False: if 'provisionaledits' in row.doc and row.doc[ 'provisionaledits'] is not None: action = 'update' try: tile = Tile.objects.get( tileid=row.doc['tileid']) prov_edit = self.get_provisional_edit( row.doc, tile, sync_user_id, db) if prov_edit is not None: tile.data = prov_edit # If there are conflicting documents, lets clear those out if '_conflicts' in row.doc: for conflict_rev in row.doc['_conflicts']: conflict_data = db.get( row.id, rev=conflict_rev) if conflict_data['provisionaledits'] != '' and \ conflict_data['provisionaledits'] is not None: if sync_user_id in conflict_data[ 'provisionaledits']: tile.data = conflict_data[ 'provisionaledits'][ sync_user_id]['value'] # Remove conflicted revision from couch db.delete(conflict_data) except Tile.DoesNotExist: action = 'create' tile = Tile(row.doc) prov_edit = self.get_provisional_edit( row.doc, tile, sync_user_id, db) if prov_edit is not None: tile.data = prov_edit self.handle_reviewer_edits(sync_user, tile) tile.save(user=sync_user) self.save_revision_log(row.doc, synclog, action) print('Tile {0} Saved'.format(row.doc['tileid'])) db.compact()
def save(self, tile, request): """ Finds the equivalen GeoJSON for a BNG Alphanumeric value and saves that value to the geojson nodegroup of the tile. Agrs: self: BNGPointToGeoJSON object. tile: Tile to attach / amend geojson_nodegroup of. request: WSGI Request used to varify call is result of user action. N.B. Function Returns if empty. """ # print 'calling save' # First let's check if this call is as a result of an inbound request (user action) or # as a result of the complementary GeoJSONToBNGPoint function saving a new BngPoint. if request is None: return bngValueReturned = "" gridSquare = { "NT": [3, 6], "NU": [4, 6], "NX": [2, 5], "NY": [3, 5], "NZ": [4, 5], "SD": [3, 4], "SE": [4, 4], "TA": [5, 4], "SJ": [3, 3], "SK": [4, 3], "TF": [5, 3], "TG": [6, 3], "SO": [3, 2], "SP": [4, 2], "TL": [5, 2], "TM": [6, 2], "SS": [2, 1], "ST": [3, 1], "SU": [4, 1], "TQ": [5, 1], "TR": [6, 1], "SV": [0, 0], "SW": [1, 0], "SX": [2, 0], "SY": [3, 0], "SZ": [4, 0], "TV": [5, 0] } bngnode = self.config[u"bng_node"] geojsonNode = self.config[u"geojson_node"] bngValueReturned = tile.data[bngnode] if bngValueReturned != None: ''' The following section turns the alphanumberic BNG value in the tile into a point geometry object and then transforms that object into WGS 1984 long/lat projection system. ''' dt = datetime.now() gridSquareLetters = bngValueReturned[0:2] bngValueNumbers = bngValueReturned[2:] splitSection = len(bngValueNumbers) / 2 gridSquareNumbers = gridSquare[gridSquareLetters] eastingValue = str(gridSquareNumbers[0]) + str( bngValueNumbers[:splitSection]) northingValue = str(gridSquareNumbers[1]) + str( bngValueNumbers[splitSection:]) osgb36PointString = 'POINT (' + eastingValue + ' ' + northingValue + ')' osgb36Point = GEOSGeometry(osgb36PointString, srid=27700) osgb36Point.transform(4326, False) pointGeoJSON = json.loads(osgb36Point.geojson) ''' This section creates a geojson object required in the format required by Arches. The date and time the object was created has also been added in the feature's properties. ''' uuidForRecord = uuid.uuid4().hex geometryValue = { "type": "FeatureCollection", "features": [{ "geometry": pointGeoJSON, "type": "Feature", "id": str(uuidForRecord), "properties": { "datetime": dt.strftime("%d/%m/%Y %H:%M:%S") } }] } geometryValueJson = geometryValue ''' The Tile.objects.filter function from tiles.py is called to return any tiles with the geojson_nodegroup value as the nodegroup_id and the current tile's resource instance ID as its resourceinstance_id value; any tiles returned are added to the previously_saved_tiles variable. If there are tiles returned then the new geojson object overwrites the current value. If there are no tiles returned, a new tile is created for the geojson nodegroup using tile.py's get_blank_tile function. If there is a key within the data object in the new node with the same id as the geojson_nodegroup value then that key/value pair are deleted. The geojson object is set at the value to the key which has the value of the geojson_node value. The new tile is saved and then the mv_geojson_geoms materialised view is refreshed so the point geometry will be displayed on the Search map. ''' previously_saved_tiles = Tile.objects.filter( nodegroup_id=self.config[u"geojson_nodegroup"], resourceinstance_id=tile.resourceinstance_id) if len(previously_saved_tiles) > 0: for p in previously_saved_tiles: p.data[geojsonNode] = geometryValueJson p.save() else: geoJSONnodegroup = Tile().get_blank_tile_from_nodegroup_id( self.config[u"geojson_nodegroup"], resourceid=tile.resourceinstance_id, parenttile=tile.parenttile) geoJSONnodegroup.data[ self.config[u"geojson_node"]] = geometryValueJson if self.config[u"geojson_nodegroup"] in geoJSONnodegroup.data: del geoJSONnodegroup.data[ self.config[u"geojson_nodegroup"]] geoJSONnodegroup.save() ''' The resource object for the tile is returned and then reindexed. ''' #resource = Resource.objects.get(resourceinstanceid=tile.resourceinstance_id) #resource.index() cursor = connection.cursor() sql = """ REFRESH MATERIALIZED VIEW mv_geojson_geoms; """ cursor.execute(sql) resource = Resource.objects.get( resourceinstanceid=tile.resourceinstance_id) #resource.index() else: pass ''' The tile is saved. ''' tile.save() return
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) if json != None: data = JSONDeserializer().deserialize(json) try: models.ResourceInstance.objects.get( pk=data['resourceinstance_id']) except ObjectDoesNotExist: resource = Resource() resource.resourceinstanceid = data['resourceinstance_id'] graphid = models.Node.objects.filter( nodegroup=data['nodegroup_id'])[0].graph_id resource.graph_id = graphid resource.save(user=request.user) resource.index() tile_id = data['tileid'] if tile_id != None and tile_id != '': old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: tile.save(request=request) if tile_id == '4345f530-aa90-48cf-b4b3-92d1185ca439': import couchdb import json as json_json couch = couchdb.Server(settings.COUCHDB_URL) for project in models.MobileSurveyModel.objects.all( ): db = couch['project_' + str(project.id)] #tile = models.TileModel.objects.get(pk='4345f530-aa90-48cf-b4b3-92d1185ca439') tile_json = json_json.loads( JSONSerializer().serialize(tile)) tile_json['_id'] = tile_json['tileid'] for row in db.view('_all_docs', include_docs=True): if 'tileid' in row.doc and tile_json[ '_id'] == row.doc['_id']: tile_json['_rev'] = row.doc['_rev'] db.save(tile_json) except ValidationError as e: return JSONResponse( { 'status': 'false', 'message': e.args }, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse( { 'status': 'false', 'message': [_('Request Failed'), _('Permission Denied')] }, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == 'delete_provisional_tile': data = request.POST if 'tileid' in data: provisionaledits = self.delete_provisional_edit(data, request) return JSONResponse(provisionaledits) else: payload = data.get('payload', None) if payload is not None: edits = jsonparser.loads(payload) for edit in edits['edits']: provisionaledits = self.delete_provisional_edit( edit, request) return JSONResponse({'result': 'success'}) return HttpResponseNotFound()
def save(self,tile,request): ## variable to control verbose output. not hooked into anywhere else in the app, ## but useful during development verbose = False if verbose: print(f"verbose: {verbose}") ## return early if there is no spatial data to use for a comparison spatial_node_id = self.config['spatial_node_id'] if tile.data[spatial_node_id] == None or tile.data[spatial_node_id] == []: ## apparently if there is None in the triggering nodegroup, ## an error will occur AFTER this function has returned. So, ## for now, setting the value to an empty list to handle this. tile.data[spatial_node_id] = [] return ## get geoms from the current tile geoms = [feature['geometry'] for feature in tile.data[spatial_node_id]['features']] ## create and iterate list of input table/field/target sets ## the UI should produce "table_name.field_name" strings table_field_targets = self.config['inputs'] for table_field_target in table_field_targets: if verbose: print(f"processing input: {table_field_target}") ## skip if the table_name.field_name input is not valid if not "." in table_field_target['table_field']: continue ## parse input sets table,field = table_field_target['table_field'].split(".")[0],table_field_target['table_field'].split(".")[1] target_node_id = table_field_target['target_node_id'] target_ng_id = models.Node.objects.filter(nodeid=target_node_id)[0].nodegroup_id # process each geom and create a list of all values vals = [] for geom in geoms: val = attribute_from_postgis(table,field,geom) vals+=val attributes = list(set(vals)) if len(attributes) == 0: continue ## get the datatype of the target node, and if necessary convert the ## attributes to value ids. note that prefLabels are expected here, ## NOT actual concept ids. what actually gets passed to the tile data ## are valueids for the preflabels, not UUIDs for the concept. node = models.Node.objects.get(pk=target_node_id) target_node_datatype = node.datatype if target_node_datatype in ["concept","concept-list"]: vals = [get_valueid_from_preflabel(v) for v in attributes] attributes = [v for v in vals if v] ## if the target node is inside of the currently edited node group, ## just set the new value right here if str(target_ng_id) == str(tile.nodegroup_id): if verbose: print(" inside same nodegroup") ## set precedent for correlating new values with target node ## datatype. the following will work on a limited basis if target_node_datatype == "concept-list": tile.data[target_node_id] = attributes elif target_node_datatype == "concept": tile.data[target_node_id] = attributes[0] else: tile.data[target_node_id] = attributes[0] tile.dirty = False continue ## if the tile that is to be updated already exists, then it is easy ## to find and update it. this should be combined with a if verbose: print(" checking for previously saved tiles with this target_ng_id") previously_saved_tiles = Tile.objects.filter(nodegroup_id=target_ng_id,resourceinstance_id=tile.resourceinstance_id) if verbose: print(f" {len(previously_saved_tiles)} found") if len(previously_saved_tiles) > 0: for t in previously_saved_tiles: if target_node_datatype == "concept-list": t.data[target_node_id] = attributes elif target_node_datatype == "concept": t.data[target_node_id] = attributes[0] else: t.data[target_node_id] = attributes[0] t.save() continue if verbose: print(" must need a brand new tile") parenttile = Tile().get_blank_tile(target_node_id,resourceid=tile.resourceinstance_id) existing_pts = Tile.objects.filter(nodegroup_id=parenttile.nodegroup_id,resourceinstance_id=tile.resourceinstance_id) ## if there is no parent tile yet, it should be fine to save the newly created one if len(existing_pts) == 0: for ng_id,tilelist in parenttile.tiles.iteritems(): if ng_id == target_ng_id: if verbose: print(" creating new parent tile and tile") for t in tilelist: if target_node_datatype == "concept-list": t.data[target_node_id] = attributes elif target_node_datatype == "concept": t.data[target_node_id] = attributes[0] else: t.data[target_node_id] = attributes[0] parenttile.save() continue ## if there is one parent tile already, then we need to relate the new tile ## to it, and then save the new tile, but not the new parent tile if len(existing_pts) == 1: for ng_id,tilelist in parenttile.tiles.iteritems(): if ng_id == target_ng_id: if verbose: print(" creating new tile and assigning to existing parent tile") for t in tilelist: if target_node_datatype == "concept-list": t.data[target_node_id] = attributes elif target_node_datatype == "concept": t.data[target_node_id] = attributes[0] else: t.data[target_node_id] = attributes[0] t.parenttile = existing_pts[0] t.save() continue ## if there are multiple parent tiles already, it's likely that the brand new ## one could be saved without any problem (as in len(existing_pts) == 0 above) ## but this has not been tested yet. if len(existing_pts) > 1: if verbose: print(" there are multiple existing parent tiles. this circumstance"\ "is not supported at this time.") continue # tos = Tile.objects.filter(resourceinstance_id=tile.resourceinstance_id) # for to in tos: # print(to.serialize()) # print(len(tos)) return
def save_geojson(self, tile, request, is_function_save_method=True): """Finds the equivalen GeoJSON for a BNG Alphanumeric value and saves that value to the geojson nodegroup of the tile. Args: self : BNGPointToGeoJSON object. tile : Tile to attach / amend geojson_nodegroup of. request : WSGI Request used to varify call is result of user action. N.B. Function Returns if empty. is_function_save_method : a bool stating whether the function calling it is the save function. """ # First let's check if this call is as a result of an inbound request (user action) or # as a result of the complementary GeoJSONToBNGPoint function saving a new BngPoint. if request is None and is_function_save_method == True: return bngValueReturned = "" gridSquare = { "NA": [0, 9], "NB": [1, 9], "NC": [2, 9], "ND": [3, 9], "NE": [4, 9], "OA": [5, 9], "OB": [6, 9], "NF": [0, 8], "NG": [1, 8], "NH": [2, 8], "NJ": [3, 8], "NK": [4, 8], "OF": [5, 8], "OG": [6, 8], "NL": [0, 7], "NM": [1, 7], "NN": [2, 7], "NO": [3, 7], "NP": [4, 7], "OL": [5, 7], "OM": [6, 7], "NQ": [0, 6], "NR": [1, 6], "NS": [2, 6], "NT": [3, 6], "NU": [4, 6], "OQ": [5, 6], "OR": [6, 6], "NV": [0, 5], "NW": [1, 5], "NX": [2, 5], "NY": [3, 5], "NZ": [4, 5], "OV": [5, 5], "OW": [6, 5], "SA": [0, 4], "SB": [1, 4], "SC": [2, 4], "SD": [3, 4], "SE": [4, 4], "TA": [5, 4], "TB": [6, 4], "SF": [0, 3], "SG": [1, 3], "SH": [2, 3], "SJ": [3, 3], "SK": [4, 3], "TF": [5, 3], "TG": [6, 3], "SL": [0, 2], "SM": [1, 2], "SN": [2, 2], "SO": [3, 2], "SP": [4, 2], "TL": [5, 2], "TM": [6, 2], "SQ": [0, 1], "SR": [1, 1], "SS": [2, 1], "ST": [3, 1], "SU": [4, 1], "TQ": [5, 1], "TR": [6, 1], "SV": [0, 0], "SW": [1, 0], "SX": [2, 0], "SY": [3, 0], "SZ": [4, 0], "TV": [5, 0], "TW": [6, 0], } bngnode = self.config["bng_node"] geojsonNode = self.config["geojson_node"] bngValueReturned = tile.data[bngnode] if bngValueReturned != None: """ The following section turns the alphanumberic BNG value in the tile into a point geometry object and then transforms that object into WGS 1984 long/lat projection system. """ dt = datetime.now() gridSquareLetters = bngValueReturned[0:2] bngValueNumbers = bngValueReturned[2:] splitSection = int(len(bngValueNumbers) / 2) gridSquareNumbers = gridSquare[gridSquareLetters] eastingValue = str(gridSquareNumbers[0]) + str(bngValueNumbers[:splitSection]) northingValue = str(gridSquareNumbers[1]) + str(bngValueNumbers[splitSection:]) osgb36PointString = "POINT (" + eastingValue + " " + northingValue + ")" osgb36Point = GEOSGeometry(osgb36PointString, srid=27700) osgb36Point.transform(4326, False) pointGeoJSON = json.loads(osgb36Point.geojson) """ This section creates a geojson object required in the format required by Arches. The date and time the object was created has also been added in the feature's properties. """ uuidForRecord = uuid.uuid4().hex bngFeature = { "geometry": pointGeoJSON, "type": "Feature", "id": str(uuidForRecord), "properties": {"datetime": dt.strftime("%d/%m/%Y %H:%M:%S"), "bngref": str(bngValueReturned)}, } geometryValue = {"type": "FeatureCollection", "features": [bngFeature]} geometryValueJson = geometryValue """ The Tile.objects.filter function from tiles.py is called to return any tiles with the geojson_nodegroup value as the nodegroup_id and the current tile's resource instance ID as its resourceinstance_id value; any tiles returned are added to the previously_saved_tiles variable. If there are tiles returned then the new geojson object overwrites the current value. If there are no tiles returned, a new tile is created for the geojson nodegroup using tile.py's get_blank_tile function. If there is a key within the data object in the new node with the same id as the geojson_nodegroup value then that key/value pair are deleted. The geojson object is set at the value to the key which has the value of the geojson_node value. The new tile is saved and then the mv_geojson_geoms materialised view is refreshed so the point geometry will be displayed on the Search map. """ if self.config["geojson_nodegroup"] == str(tile.nodegroup_id): tile.data[geojsonNode] = geometryValueJson else: previously_saved_tiles = Tile.objects.filter( nodegroup_id=self.config["geojson_nodegroup"], resourceinstance_id=tile.resourceinstance_id ) if len(previously_saved_tiles) > 0: for p in previously_saved_tiles: old_geojson = p.data[geojsonNode] p.data[geojsonNode] = geometryValueJson for f in old_geojson["features"]: if "bngref" not in f["properties"]: p.data[geojsonNode]["features"].append(f) p.save() else: new_geojson_tile = Tile().get_blank_tile_from_nodegroup_id( self.config["geojson_nodegroup"], resourceid=tile.resourceinstance_id, parenttile=tile.parenttile ) new_geojson_tile.data[self.config["geojson_node"]] = geometryValueJson if self.config["geojson_nodegroup"] in new_geojson_tile.data: del new_geojson_tile.data[self.config["geojson_nodegroup"]] new_geojson_tile.save() cursor = connection.cursor() sql = """ SELECT * FROM refresh_geojson_geometries(); """ cursor.execute(sql) # else: pass return
def post(self, request): if self.action == 'update_tile': json = request.POST.get('data', None) accepted_provisional = request.POST.get('accepted_provisional', None) if accepted_provisional != None: accepted_provisional_edit = JSONDeserializer().deserialize( accepted_provisional) if json != None: data = JSONDeserializer().deserialize(json) if data['resourceinstance_id'] == '': data['resourceinstance_id'] = uuid.uuid4() try: models.ResourceInstance.objects.get( pk=data['resourceinstance_id']) except ObjectDoesNotExist: resource = Resource() graphid = models.Node.objects.filter( nodegroup=data['nodegroup_id'])[0].graph_id resource.graph_id = graphid resource.save(user=request.user) data['resourceinstance_id'] = resource.pk resource.index() tile_id = data['tileid'] if tile_id != None and tile_id != '': try: old_tile = Tile.objects.get(pk=tile_id) clean_resource_cache(old_tile) except ObjectDoesNotExist: return JSONResponse( { 'status': 'false', 'message': [ _('This tile is no longer available'), _('It was likely deleted by another user') ] }, status=500) tile = Tile(data) if tile.filter_by_perm(request.user, 'write_nodegroup'): with transaction.atomic(): try: if accepted_provisional == None: try: tile.save(request=request) except TileValidationError as e: resource_tiles = models.TileModel.objects.filter( resourceinstance=tile.resourceinstance) if resource_tiles.count() == 0: Resource.objects.get( pk=tile.resourceinstance_id ).delete(request.user, 'test') return JSONResponse( { 'status': 'false', 'message': [ e.message, _('Unable to Save. Please verify your input is valid' ) ] }, status=500) except Exception as e: message = "Unable to save. A {0} has occurred. Arguments: {1!r}".format( type(e).__name__, e.args) return JSONResponse( { 'status': 'false', 'message': [ message, _('Please contact your system administrator' ) ] }, status=500) else: if accepted_provisional is not None: provisional_editor = User.objects.get( pk=accepted_provisional_edit["user"]) tile.save( provisional_edit_log_details={ "user": request.user, "action": "accept edit", "edit": accepted_provisional_edit, "provisional_editor": provisional_editor }) if tile.provisionaledits is not None and str( request.user.id) in tile.provisionaledits: tile.data = tile.provisionaledits[str( request.user.id)]['value'] except ValidationError as e: return JSONResponse( { 'status': 'false', 'message': e.args }, status=500) except Exception as e: exception_title = 'Saving tile failed' exception_message = str(e) if hasattr(e, 'message') and e.message: exception_message += "({0})".format(e.message) logger.error(exception_title + ''' [Tile id: {tile_id}] \ [Exception message: {message}] \ [Exception trace: {trace}]'''.format( tile_id=tile_id, message=exception_message, trace=traceback.format_exc())) return JSONResponse( { 'status': 'false', 'message': [ _(exception_title), _(str(exception_message)) ] }, status=500) tile.after_update_all() clean_resource_cache(tile) update_system_settings_cache(tile) return JSONResponse(tile) else: return JSONResponse( { 'status': 'false', 'message': [_('Request Failed'), _('Permission Denied')] }, status=500) if self.action == 'reorder_tiles': json = request.body if json != None: data = JSONDeserializer().deserialize(json) if 'tiles' in data and len(data['tiles']) > 0: sortorder = 0 with transaction.atomic(): for tile in data['tiles']: t = Tile(tile) if t.filter_by_perm(request.user, 'write_nodegroup'): t.sortorder = sortorder t.save(update_fields=['sortorder'], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == 'delete_provisional_tile': user = request.POST.get('user', None) tileid = request.POST.get('tileid', None) users = request.POST.get('users', None) tile = Tile.objects.get(tileid=tileid) is_provisional = tile.is_provisional() if tileid is not None and user is not None: provisionaledits = self.delete_provisional_edit( tile, user, reviewer=request.user) elif tileid is not None and users is not None: users = jsonparser.loads(users) for user in users: self.delete_provisional_edit(tile, user, reviewer=request.user) if is_provisional == True: return JSONResponse({'result': 'delete'}) else: return JSONResponse({'result': 'success'}) return HttpResponseNotFound()
def post(self, request, graphid=None): try: body = json.loads(request.body) file_data = body['file_data'] column_name_to_node_data_map = body['column_name_to_node_data_map'] nodegroup_data = {} for node_data in column_name_to_node_data_map.values(): nodegroup_id = node_data.get('nodegroup_id') if nodegroup_id: if not nodegroup_data.get(nodegroup_id): nodegroup_data[nodegroup_id] = [] nodegroup_data[nodegroup_id].append(node_data['node_id']) for file_datum in file_data: for row_data in file_datum['data']: resource_instance = Resource(graph_id=graphid) resource_instance.save() parsed_data = row_data['parsed_data'] tile_data = {} for nodegroup_id in nodegroup_data.keys(): if not tile_data.get(nodegroup_id): tile_data[nodegroup_id] = {} for node_id in nodegroup_data[nodegroup_id]: tile_data[nodegroup_id][node_id] = parsed_data.get( node_id) for nodegroup_id in tile_data.keys(): tile = TileProxyModel( data=tile_data[nodegroup_id], resourceinstance=resource_instance, nodegroup_id=nodegroup_id, # nodegroup_id = 'f7c974a0-29f4-11eb-8487-aae9fe8789ac', # Related Observations ) tile.save() file_datum['created_resources'][row_data['row_id']] = { 'resourceinstance_id': str(resource_instance.pk), 'row_id': row_data['row_id'], 'tile_data': tile_data, } return JSONResponse({ 'file_data': file_data, }, status=200) except Exception as e: if settings.DEBUG is True: exc_type, exc_value, exc_traceback = sys.exc_info() formatted = traceback.format_exception(exc_type, exc_value, exc_traceback) if len(formatted): for message in formatted: print(message) return JSONResponse( {"error": "resource data could not be saved: %s" % e}, status=500, reason=e)
def push_edits_to_db(self, synclog=None, userid=None): # read all docs that have changes # save back to postgres db db = self.couch.create_db("project_" + str(self.id)) user_lookup = {} is_reviewer = False sync_user = None sync_user_id = None if userid is not None: sync_user = User.objects.get(pk=userid) sync_user_id = str(sync_user.id) with transaction.atomic(): couch_docs = self.couch.all_docs(db) for row in couch_docs: if row.doc["type"] == "resource": if self.check_if_revision_exists(row.doc) is False: if "provisional_resource" in row.doc and row.doc[ "provisional_resource"] == "true": resourceinstance, created = ResourceInstance.objects.update_or_create( resourceinstanceid=uuid.UUID( str(row.doc["resourceinstanceid"])), defaults=dict(graph_id=uuid.UUID( str(row.doc["graph_id"]))), ) if created is True: self.save_revision_log(row.doc, synclog, "create") else: self.save_revision_log(row.doc, synclog, "update") print("Resource {0} Saved".format( row.doc["resourceinstanceid"])) else: print("{0}: already saved".format(row.doc["_rev"])) for row in couch_docs: if row.doc[ "type"] == "tile" and ResourceInstance.objects.filter( pk=row.doc["resourceinstance_id"]).exists(): if self.check_if_revision_exists(row.doc) is False: if "provisionaledits" in row.doc and row.doc[ "provisionaledits"] is not None: action = "update" try: tile = Tile.objects.get( tileid=row.doc["tileid"]) prov_edit = self.get_provisional_edit( row.doc, tile, sync_user_id, db) if prov_edit is not None: tile.data = prov_edit # If there are conflicting documents, lets clear those out if "_conflicts" in row.doc: for conflict_rev in row.doc["_conflicts"]: conflict_data = db.get( row.id, rev=conflict_rev) if conflict_data[ "provisionaledits"] != "" and conflict_data[ "provisionaledits"] is not None: if sync_user_id in conflict_data[ "provisionaledits"]: tile.data = conflict_data[ "provisionaledits"][ sync_user_id]["value"] # Remove conflicted revision from couch db.delete(conflict_data) except Tile.DoesNotExist: action = "create" tile = Tile(row.doc) prov_edit = self.get_provisional_edit( row.doc, tile, sync_user_id, db) if prov_edit is not None: tile.data = prov_edit self.handle_reviewer_edits(sync_user, tile) tile.save(user=sync_user) self.save_revision_log(row.doc, synclog, action) print("Tile {0} Saved".format(row.doc["tileid"])) db.compact()
def post(self, request): if self.action == "update_tile": json = request.POST.get("data", None) accepted_provisional = request.POST.get("accepted_provisional", None) if accepted_provisional is not None: accepted_provisional_edit = JSONDeserializer().deserialize( accepted_provisional) if json is not None: data = JSONDeserializer().deserialize(json) data[ "resourceinstance_id"] = "" if "resourceinstance_id" not in data else data[ "resourceinstance_id"] if data["resourceinstance_id"] == "": data["resourceinstance_id"] = uuid.uuid4() try: models.ResourceInstance.objects.get( pk=data["resourceinstance_id"]) except ObjectDoesNotExist: try: resource = Resource( uuid.UUID(str(data["resourceinstance_id"]))) except ValueError: resource = Resource() graphid = models.Node.objects.filter( nodegroup=data["nodegroup_id"])[0].graph_id resource.graph_id = graphid try: resource.save(user=request.user) data["resourceinstance_id"] = resource.pk resource.index() except ModelInactiveError as e: message = _( "Unable to save. Please verify the model status is active" ) return JSONResponse( { "status": "false", "message": [_(e.title), _(str(message))] }, status=500) tile_id = data["tileid"] resource_instance = models.ResourceInstance.objects.get( pk=data["resourceinstance_id"]) is_active = resource_instance.graph.isactive if tile_id is not None and tile_id != "": try: old_tile = Tile.objects.get(pk=tile_id) except ObjectDoesNotExist as e: return self.handle_save_error( e, _("This tile is no longer available"), _("It was likely deleted by another user")) tile = Tile(data) if tile.filter_by_perm( request.user, "write_nodegroup") and is_active is True: try: with transaction.atomic(): try: if accepted_provisional is None: try: tile.save(request=request) except TileValidationError as e: resource_tiles = models.TileModel.objects.filter( resourceinstance=tile. resourceinstance) if resource_tiles.count() == 0: Resource.objects.get( pk=tile.resourceinstance_id ).delete(request.user) title = _( "Unable to save. Please verify your input is valid" ) return self.handle_save_error( e, tile_id, title=title) except ModelInactiveError as e: message = _( "Unable to save. Please verify the model status is active" ) return JSONResponse( { "status": "false", "message": [_(e.title), _(str(message))] }, status=500) else: if accepted_provisional is not None: provisional_editor = User.objects.get( pk=accepted_provisional_edit[ "user"]) prov_edit_log_details = { "user": request.user, "action": "accept edit", "edit": accepted_provisional_edit, "provisional_editor": provisional_editor, } tile.save(request=request, provisional_edit_log_details= prov_edit_log_details) if tile.provisionaledits is not None and str( request.user.id ) in tile.provisionaledits: tile.data = tile.provisionaledits[str( request.user.id)]["value"] except Exception as e: return self.handle_save_error(e, tile_id) tile.after_update_all() update_system_settings_cache(tile) except Exception as e: return self.handle_save_error(e, tile_id) return JSONResponse(tile) elif is_active is False: response = { "status": "false", "message": [ _("Request Failed"), _("Unable to Save. Verify model status is active") ] } return JSONResponse(response, status=500) else: return JSONErrorResponse(_("Request Failed"), _("Permission Denied")) if self.action == "reorder_tiles": json = request.body if json is not None: data = JSONDeserializer().deserialize(json) if "tiles" in data and len(data["tiles"]) > 0: sortorder = 0 with transaction.atomic(): for tile in data["tiles"]: t = Tile(tile) if t.filter_by_perm(request.user, "write_nodegroup"): t.sortorder = sortorder t.save(update_fields=["sortorder"], request=request) sortorder = sortorder + 1 return JSONResponse(data) if self.action == "delete_provisional_tile": user = request.POST.get("user", None) tileid = request.POST.get("tileid", None) users = request.POST.get("users", None) tile = Tile.objects.get(tileid=tileid) is_provisional = tile.is_provisional() if tileid is not None and user is not None: provisionaledits = self.delete_provisional_edit( tile, user, request) elif tileid is not None and users is not None: users = jsonparser.loads(users) for user in users: self.delete_provisional_edit(tile, user, request) if is_provisional == True: return JSONResponse({"result": "delete"}) else: return JSONResponse({"result": "success"}) return HttpResponseNotFound()