def wfs_edit(): user = current_user form = WFSEditForm() add_layer_form = WFSAddLayerForm() couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) if add_layer_form.validate_on_submit(): title = add_layer_form.data.get('new_layer') layer = re.sub(r'[^a-z0-9]*', '', title.lower()) couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) schema = tinyows.base_schema() if couch.layer_schema(layer): flash(_('Layer %(title)s already exists', title=title), 'error') else: couch.store_layer_schema(layer, schema, title=title) flash(_('Layer %(title)s created', title=title)) form.layer.choices = [(layer, title) for layer, title in couch.get_layer_names() if layer != current_app.config.get('USER_READONLY_LAYER')] if form.validate_on_submit(): layer = form.data.get('layer', current_app.config.get('USER_WORKON_LAYER')) if not int(form.data['external_editor']): return redirect(url_for('.wfs_edit_layer', layer=layer)) else: return redirect(url_for('.wfs_session', layer=layer)) return render_template('maps/wfs_edit.html', form=form, add_layer_form=add_layer_form, not_removable_layer=current_app.config.get('USER_WORKON_LAYER'))
def write_back(layer=None, ajax=True): user = current_user connection = psycopg2.connect( database=current_app.config.get('TEMP_PG_DB'), host=current_app.config.get('TEMP_PG_HOST'), user=current_app.config.get('TEMP_PG_USER'), password=current_app.config.get('TEMP_PG_PASSWORD'), sslmode='allow', ) couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) schema = couch.layer_schema(layer) extend_schema_for_couchdb(schema) tablename = 'tmp%s%s' % (user.id, layer) tmp_db = TempPGDB(connection=connection, tablename=tablename, schema=schema) couch.store_features(layer, tmp_db.load_features(), delete_missing=tmp_db.imported_feature_ids()) connection.close() # write changes back to PostGIS to prevent multiple inserts create_wfs(user, [layer]) signals.features_updated.send(user) if ajax: return Response(response='success', status=200, headers=None, mimetype='application/json', content_type=None)
def create(self, user_token, layer): from gbi_server.model import User from gbi_server.model import WMTS from gbi_server.extensions import db user = User.by_authproxy_token(user_token) if not user: raise InvalidUserToken() result = db.session.query(WMTS, ST_Transform( WMTS.view_coverage, 3857)).filter_by(name=layer).first() if result: wmts, view_coverage = result if wmts and wmts.is_public: return to_shape(view_coverage) if user.is_customer: couch_url = self.couchdb_url couchdb = CouchDBBox( couch_url, '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) geom = couchdb.layer_extent(self.geometry_layer) return optimize_geometry(geom) if geom else None elif user.is_service_provider: couch_url = self.couchdb_url couchdb = CouchDBBox( couch_url, '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) geom = couchdb.layer_extent() return optimize_geometry(geom) if geom else None elif user.is_admin or user.is_consultant: # permit access to everything return box(-20037508.3428, -20037508.3428, 20037508.3428, 20037508.3428) return None
def wfs_edit_layer(layer=None): form = WFSSearchForm() user = current_user wfs_session = WFSSession.by_active_user_layer(layer, user) if wfs_session: flash(_('external edit in progress')) return redirect(url_for('.wfs_session', layer=layer)) couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) try: wfs_layers, wfs_layer_token = create_wfs(user, editable_layers=[layer]) except MissingSchemaError: flash(_('layer unknown or without schema')) abort(404) features = [feature for feature in couch.iter_layer_features(current_app.config.get('USER_READONLY_LAYER')) if isinstance(feature['geometry'], dict)] data_extent = couch.layer_extent(layer) if not data_extent: data_extent = couch.layer_extent(current_app.config.get('USER_READONLY_LAYER')) if not data_extent: result = db.session.query(WMTS, ST_Transform(WMTS.view_coverage, 3857)).order_by(desc(WMTS.is_background_layer)).first() if result: data_extent = to_shape(result[1]) titles = dict(couch.get_layer_names()) return render_template( 'maps/wfs.html', form=form, wfs=wfs_layers, layers=WMTS.query.all(), read_only_features=features, read_only_schema=couch.layer_schema(layer)['properties'], read_only_layer_name=current_app.config.get('AREA_BOX_TITLE'), editable_layer=layer, editable_layer_title=titles[layer], data_extent=data_extent.bounds if data_extent else None, user=current_user )
def wfs_remove_layer(layer=None): user = current_user if layer in [current_app.config.get('USER_READONLY_LAYER'), current_app.config.get('USER_WORKON_LAYER')]: flash(_('not allowed to remove this layer')) return redirect(url_for('.wfs_edit')) wfs_session = WFSSession.by_active_user_layer(layer, user) if wfs_session: flash(_('external edit in progress')) return redirect(url_for('.wfs_session', layer=layer)) couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) try: couch.clear_layer(layer) flash(_('Layer %(layer)s removed', layer=layer)) except CouchDBError: flash(_('Could not remove layer %(layer)s', layer=layer), 'error') return redirect(url_for('.wfs_edit'))
def wmts(): couch = CouchDBBox( current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, current_user.id) ) features = [feature for feature in couch.iter_features() if isinstance(feature['geometry'], dict)] vector_layers = [] vector_layers.append({ 'name': SystemConfig.AREA_BOX_TITLE, 'features': features, 'readonly': True, }) wmts_layers = WMTS.query.all() return render_template( 'maps/map.html', wmts_layers=wmts_layers, vector_layers=vector_layers, user=current_user )
def get_context_document(): init_user_boxes(g.user, current_app.config.get('COUCH_DB_URL')) wmts_sources = db.session.query( WMTS, ST_AsGeoJSON(ST_Transform(WMTS.view_coverage, 3857))).order_by( desc(WMTS.is_background_layer)).all() wms_sources = db.session.query( WMS, ST_AsGeoJSON(ST_Transform(WMS.view_coverage, 3857))).order_by( desc(WMS.is_background_layer)).all() wfs_sources = db.session.query(WFS).all() response = { "version": "0.2", "portal": { "prefix": current_app.config['PORTAL_PREFIX'], "title": current_app.config['PORTAL_TITLE'], }, "wmts_sources": [], "wms_sources": [], "wfs_sources": [], "couchdb_sources": [], } couchdb = CouchDBBox(current_app.config['COUCH_DB_URL'], '%s_%s' % (SystemConfig.AREA_BOX_NAME, g.user.id)) for source in wmts_sources: wmts, view_coverage = source geom = json.loads(view_coverage) response['wmts_sources'].append({ "name": wmts.name, "title": wmts.title, "url": wmts.client_url(external=True), "format": wmts.format, "overlay": wmts.is_overlay, "username": wmts.username, "password": wmts.password, "is_public": wmts.is_public, "is_protected": wmts.is_protected, "is_background_layer": wmts.is_background_layer, "max_tiles": wmts.max_tiles, "view_restriction": { "zoom_level_start": wmts.view_level_start, "zoom_level_end": wmts.view_level_end, "geometry": geom }, "download_restriction": { "zoom_level_start": wmts.view_level_start, "zoom_level_end": wmts.view_level_end, } }) for source in wms_sources: wms, view_coverage = source geom = json.loads(view_coverage) response['wms_sources'].append({ "name": wms.name, "title": wms.title, "url": wms.url, "layer": wms.layer, "format": wms.format, "overlay": wms.is_overlay, "username": wms.username, "password": wms.password, "is_public": wms.is_public, "is_protected": wms.is_protected, "srs": wms.srs, "wms_version": wms.version, "view_restriction": { "zoom_level_start": wms.view_level_start, "zoom_level_end": wms.view_level_end, "geometry": geom }, "download_restriction": { "zoom_level_start": wms.view_level_start, "zoom_level_end": wms.view_level_end, } }) for wfs in wfs_sources: response['wfs_sources'].append({ 'id': wfs.id, 'name': wfs.name, 'layer': wfs.layer, 'host': wfs.host, 'url': wfs.url, 'srs': wfs.srs, 'geometry_field': wfs.geometry, 'feature_ns': wfs.ns_uri, 'typename': wfs.ns_prefix, 'search_property': wfs.search_property, 'username': wfs.username, 'password': wfs.password, 'is_protected': wfs.is_protected, }) if current_app.config['FEATURE_AREA_BOXES']: response['couchdb_sources'].append({ "name": _('area box'), "url": current_app.config['COUCH_DB_URL'], "dbname": '%s_%s' % (SystemConfig.AREA_BOX_NAME, g.user.id), "username": '******' % g.user.id, "password": g.user.authproxy_token, "writable": True, "dbname_user": SystemConfig.AREA_BOX_NAME_LOCAL, }) if current_app.config['FEATURE_DOC_BOXES']: if g.user.is_consultant: response['couchdb_sources'].append({ "name": _('file box'), "url": current_app.config['COUCH_DB_URL'], "dbname": '%s_%s' % (SystemConfig.FILE_BOX_NAME, g.user.id), "username": '******' % g.user.id, "password": g.user.authproxy_token, "writable": True, "dbname_user": SystemConfig.FILE_BOX_NAME_LOCAL, }) else: response['couchdb_sources'].append({ "name": _('consultant box'), "url": current_app.config['COUCH_DB_URL'], "dbname": '%s_%s' % (SystemConfig.DOWNLOAD_BOX_NAME, g.user.id), "username": '******' % g.user.id, "password": g.user.authproxy_token, "writable": False, "dbname_user": SystemConfig.DOWNLOAD_BOX_NAME_LOCAL, }) response['couchdb_sources'].append({ "name": _('uploadbox'), "url": current_app.config['COUCH_DB_URL'], "dbname": '%s_%s' % (SystemConfig.UPLOAD_BOX_NAME, g.user.id), "username": '******' % g.user.id, "password": g.user.authproxy_token, "writable": True, "dbname_user": SystemConfig.UPLOAD_BOX_NAME_LOCAL, }) if current_app.config['PARCEL_SEARCH_DATABASE_URI']: response['parcel_search_url'] = url_for('search.query', token=g.user.authproxy_token, _external=True) response['logging'] = { 'url': url_for('logserv.log', user_token=g.user.authproxy_token, _external=True), } response['update_coverage'] = { 'url': url_for('authproxy.update_download_coverage', user_token=g.user.authproxy_token, _external=True), } response['user'] = { 'email': g.user.email, 'type': g.user.type, 'type_name': g.user.type_name, } return json.dumps(response)
def create_wfs(user=None, editable_layers=None): connection = psycopg2.connect( database=current_app.config.get('TEMP_PG_DB'), host=current_app.config.get('TEMP_PG_HOST'), user=current_app.config.get('TEMP_PG_USER'), password=current_app.config.get('TEMP_PG_PASSWORD'), sslmode='allow', ) couch = CouchDBBox(current_app.config.get('COUCH_DB_URL'), '%s_%s' % (SystemConfig.AREA_BOX_NAME, user.id)) wfs_layer_token = uuid.uuid4().hex wfs = [] # create layer to edit tinyows_layers = [] titles = dict(couch.get_layer_names()) for layer in editable_layers: wfs_layer = { 'id': id, 'name': titles[layer], 'layer': layer, 'url': url_for('.tinyows_wfs', token=wfs_layer_token, _external=True) + '?', 'srs': 'EPSG:3857', 'geometry_field': 'geometry', 'wfs_version': '1.1.0', 'feature_ns': current_app.config.get('TINYOWS_NS_URI'), 'typename': current_app.config.get('TINYOWS_NS_PREFIX'), 'writable': False, 'display_in_layerswitcher': True, } schema = couch.layer_schema(layer) if not schema or 'properties' not in schema: raise MissingSchemaError('no schema found for layer %s' % layer) extend_schema_for_couchdb(schema) # tinyows layername must not contain underscores tablename = 'tmp%s%s' % (user.id, layer) tmp_db = TempPGDB(connection=connection, tablename=tablename, schema=schema) tmp_db.create_table() tmp_db.insert_features(couch.iter_layer_features(layer)) # TODO remember created table in new model, store wfs_layer_token # and remove old tinyows configs on update wfs_layer['layer'] = tablename wfs_layer['writable'] = current_app.config.get('USER_READONLY_LAYER') != layer tinyows_layers.append({ 'name': tablename, 'title': wfs_layer['name'], 'writable': '1' if wfs_layer['writable'] else '0', }) wfs.append(wfs_layer) connection.commit() connection.close() ensure_dir(current_app.config.get('TINYOWS_TMP_CONFIG_DIR')) tinyows_config = os.path.join( current_app.config.get('TINYOWS_TMP_CONFIG_DIR'), wfs_layer_token + '.xml') tinyows.build_config(current_app, tinyows_layers, wfs_layer_token, tinyows_config) # wfs_layers for search wfs_search = db.session.query(WFS).all() for layer in wfs_search: wfs.append({ 'id': layer.id, 'name': layer.name, 'layer': layer.layer, 'url': layer.url, 'srs': layer.srs, 'geometry_field': layer.geometry, 'wfs_version': '1.1.0', 'feature_ns': layer.ns_uri, 'typename': layer.ns_prefix, 'writable': False, 'search_property': layer.search_property, 'display_in_layerswitcher': False, }) return wfs, wfs_layer_token