Skip to content
Merged
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
69 changes: 17 additions & 52 deletions src/search_geom_service.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
from collections import OrderedDict
import os
import re
from flask import json
from uuid import UUID
from sqlalchemy.sql import text as sql_text

from flask import json
from qwc_services_core.database import DatabaseEngine
from qwc_services_core.permissions_reader import PermissionsReader
from qwc_services_core.runtime_config import RuntimeConfig
from qwc_services_core.database import DatabaseEngine
from sqlalchemy.sql import text as sql_text

from search_resources import SearchResources

class SearchGeomService():
# Extract coords from bbox string like
# BOX(2644230.6300308 1246806.79350726,2644465.86084414 1246867.82022007)
BBOX_RE = re.compile(r'^BOX\((-?\d+(\.\d+)?) (-?\d+(\.\d+)?),(-?\d+(\.\d+)?) (-?\d+(\.\d+)?)\)$')


class SearchGeomService:
"""SearchGeomService class

Subset of Data Service for getting feature geometries.
Expand All @@ -24,8 +29,8 @@ def __init__(self, tenant, logger):

config_handler = RuntimeConfig("search", logger)
config = config_handler.tenant_config(tenant)
self.resources = self._load_resources(config)
self.permissions_handler = PermissionsReader(tenant, logger)
permissions = PermissionsReader(tenant, logger)
self.resources = SearchResources(config, permissions)

self.db_engine = DatabaseEngine()
self.dbs = {} # db connections with db_url as key
Expand All @@ -44,9 +49,10 @@ def query(self, identity, dataset, filterexpr):
:param str dataset: Dataset ID
:param str filterexpr: JSON serialized array of filter expressions: [["<attr>", "=", "<value>"]]
"""
resource_cfg = self._search_permissions(identity).get(dataset)
if resource_cfg is not None and len(resource_cfg) == 1 \
and filterexpr is not None:
solr_facets = self.resources.solr_facets(identity)
resource_cfg = solr_facets.get(dataset)

if resource_cfg is not None and len(resource_cfg) == 1 and filterexpr is not None:
# Column for feature ID. If unset, field from filterexpr is used
self.primary_key = resource_cfg[0].get('search_id_col')
# parse and validate input filter
Expand All @@ -68,26 +74,6 @@ def query(self, identity, dataset, filterexpr):
else:
return {'error': "Dataset not found or permission error"}

def _search_permissions(self, identity):
"""Return permitted search facets.

:param str identity: User identity
"""
# get permitted facets
permitted_facets = self.permissions_handler.resource_permissions(
'solr_facets', identity
)
# unique set
permitted_facets = set(permitted_facets)

# filter by permissions
facets = {}
for facet in self.resources['facets']:
if facet in permitted_facets or '*' in permitted_facets:
facets[facet] = self.resources['facets'][facet]

return facets

def _index(self, filterexpr, cfg):
"""Find features by filter query.

Expand Down Expand Up @@ -220,24 +206,3 @@ def _feature_from_query(self, row):
'geometry': json.loads(row['json_geom'] or 'null'),
'properties': {}
}

def _load_resources(self, config):
"""Load service resources from config.

:param RuntimeConfig config: Config handler
"""
# collect service resources (group by facet name)
facets = {}
for facet in config.resources().get('facets', []):
if facet['name'] not in facets:
facets[facet['name']] = []
facets[facet['name']].append(facet)

return {
'facets': facets
}


# Extract coords from bbox string like
# BOX(2644230.6300308 1246806.79350726,2644465.86084414 1246867.82022007)
BBOX_RE = re.compile(r'^BOX\((-?\d+(\.\d+)?) (-?\d+(\.\d+)?),(-?\d+(\.\d+)?) (-?\d+(\.\d+)?)\)$')
59 changes: 59 additions & 0 deletions src/search_resources.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
from qwc_services_core.runtime_config import RuntimeConfig


class SearchResources:
"""
Shared resources for search services.
"""

def __init__(self, config, permissions):
self.resources = self._load_resources(config)
self.permissions = permissions

def _load_resources(self, config):
"""Load service resources from config.

:param RuntimeConfig config: Config handler
"""
# collect service resources (group by facet name)
facets = {}
for facet in config.resources().get('facets', []):
if facet['name'] not in facets:
facets[facet['name']] = []
facets[facet['name']].append(facet)

return {
'facets': facets
}

def solr_facets(self, identity):
"""Return permitted search facets.

:param str identity: User identity
"""
# get permitted facets
permitted_facets = self.permissions.resource_permissions(
'solr_facets', identity
)
all_facets_permitted = '*' in permitted_facets

facets = {}

for facet, config in self.resources['facets'].items():
if all_facets_permitted or facet in permitted_facets:
facets[facet] = config

return facets

def dataproducts(self, identity):
"""Return permitted dataproducts.

:param str identity: User identity
"""
# get permitted dataproducts
permitted_dataproducts = self.permissions.resource_permissions(
'dataproducts', identity
)

# return unique sorted dataproducts
return sorted(list(set(permitted_dataproducts)))
15 changes: 6 additions & 9 deletions src/server.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
from flask import Flask, Request as RequestBase, request, jsonify
from flask_restx import Api, Resource, fields, reqparse
from werkzeug.exceptions import BadRequest

from qwc_services_core.api import create_model, CaseInsensitiveArgument
from qwc_services_core.auth import auth_manager, optional_auth, get_identity
from flask import Flask, jsonify, request
from flask_restx import Api, Resource
from qwc_services_core.auth import auth_manager, get_identity, optional_auth
from qwc_services_core.runtime_config import RuntimeConfig
from qwc_services_core.tenant_handler import (
TenantHandler, TenantPrefixMiddleware, TenantSessionInterface)
from qwc_services_core.tenant_handler import (TenantHandler, TenantPrefixMiddleware, TenantSessionInterface)

from search_geom_service import SearchGeomService # noqa: E402
from solr_search_service import SolrClient # noqa: E402
from trgm_search_service import TrgmClient # noqa: E402
from search_geom_service import SearchGeomService # noqa: E402

# Flask application
app = Flask(__name__)
Expand Down
Loading