diff --git a/README.md b/README.md index 219ac12..4f2893d 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,8 @@ Examples: "info_table": "qwc_geodb.ne_10m_admin_0_countries", "info_geom_col": "wkb_geometry", "info_display_col": "name", - "info_title": "Country" + "info_title": "Country", + "info_id": "country" } } ``` @@ -44,6 +45,7 @@ Examples: "info_geom_col": "wkb_geometry", "info_display_col": "name", "info_title": "Country", + "info_id": "country", "info_where": "pop_est > 600000" } } @@ -60,17 +62,20 @@ Examples: "info_table": "qwc_geodb.ne_10m_admin_0_countries", "info_geom_col": "wkb_geometry", "info_display_col": "name", - "info_title": "Country" + "info_title": "Country", + "info_id": "country" }, { "db_url": "postgresql:///?service=qwc_geodb", "info_sql": "SELECT type FROM qwc_geodb.ne_10m_admin_0_countries WHERE ST_contains(wkb_geometry, ST_SetSRID(ST_Point(:x, :y), :srid)) LIMIT 1", - "info_title": "Type" + "info_title": "Type", + "info_id": "type" }, { "db_url": "postgresql:///?service=qwc_geodb", "info_sql": "SELECT abbrev, postal, subregion FROM qwc_geodb.ne_10m_admin_0_countries WHERE ST_contains(wkb_geometry, ST_SetSRID(ST_Point(:x, :y), :srid)) LIMIT 1", - "info_title": ["Abbreviation", "Postal Code", "Subregion"] + "info_title": ["Abbreviation", "Postal Code", "Subregion"], + "info_id": "region" } ] } @@ -90,6 +95,52 @@ Config options in the config file can be overridden by equivalent uppercase envi | `INFO_TITLE` | Display title | +### Permissions + + +* [JSON schema](https://github.com/qwc-services/qwc-services-core/blob/master/schemas/qwc-services-permissions.json) +* File location: `$CONFIG_PATH//permissions.json` + +Example: +```json +{ + "$schema": "https://raw.githubusercontent.com/qwc-services/qwc-services-core/master/schemas/qwc-services-permissions.json", + "users": [ + { + "name": "demo", + "groups": ["demo"], + "roles": [] + } + ], + "groups": [ + { + "name": "demo", + "roles": ["demo"] + } + ], + "roles": [ + { + "role": "public", + "permissions": { + "mapinfo_queries": [ + "country", + "type", + "region" + ] + } + }, + { + "role": "demo", + "permissions": { + "mapinfo_queries": [] + } + } + ] +} +``` + + + Usage ----- diff --git a/schemas/qwc-mapinfo-service.json b/schemas/qwc-mapinfo-service.json index 166416d..39a046c 100644 --- a/schemas/qwc-mapinfo-service.json +++ b/schemas/qwc-mapinfo-service.json @@ -43,6 +43,10 @@ "type": "string" } }, + "info_id": { + "description": "ID for permission checks", + "type": "string" + }, "info_where": { "description": "Additional WHERE query", "type": "string" @@ -72,6 +76,13 @@ }, "info_title": { "description": "Display title", + "type": ["string", "array"], + "items": { + "type": "string" + } + }, + "info_id": { + "description": "ID for permission checks", "type": "string" }, "info_where": { diff --git a/src/server.py b/src/server.py index 97cd079..7aa54e8 100644 --- a/src/server.py +++ b/src/server.py @@ -1,22 +1,16 @@ -from io import BytesIO import re -import sys -from flask import Flask, request, jsonify -from flask_restx import Resource, fields, reqparse -import requests - -from sqlalchemy.sql import text as sql_text - -from qwc_services_core.api import Api -from qwc_services_core.api import CaseInsensitiveArgument +from flask import Flask, jsonify +from flask_restx import reqparse, Resource +from qwc_services_core.api import Api, CaseInsensitiveArgument from qwc_services_core.app import app_nocache -from qwc_services_core.auth import auth_manager, optional_auth +from qwc_services_core.auth import auth_manager, get_identity, optional_auth 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.tenant_handler import ( TenantHandler, TenantPrefixMiddleware, TenantSessionInterface) -from qwc_services_core.runtime_config import RuntimeConfig - +from sqlalchemy.sql import text as sql_text # Flask application app = Flask(__name__) @@ -69,6 +63,12 @@ def get(self): config_handler = RuntimeConfig("mapinfo", app.logger) config = config_handler.tenant_config(tenant) + permissions_handler = PermissionsReader(tenant, app.logger) + permitted_queries = permissions_handler.resource_permissions( + 'mapinfo_queries', get_identity() + ) + all_queries_permitted = '*' in permitted_queries + try: pos = args['pos'].split(',') pos = [float(pos[0]), float(pos[1])] @@ -84,6 +84,10 @@ def get(self): queries = config.get('queries') or [config] + # filter queries by permissions + if not all_queries_permitted: + queries = [q for q in queries if q.get('info_id') in permitted_queries] + for config in queries: result = self.__process_query(config, pos, srid) if result: