def __init__(self, tenant, logger):
        """Constructor

        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("legend", logger)
        config = config_handler.tenant_config(tenant)

        # get internal QGIS server URL from config
        self.qgis_server_url = config.get(
            'default_qgis_server_url',
            'http://localhost:8001/ows/').rstrip('/') + '/'

        # get path to legend images from config
        self.legend_images_path = config.get('legend_images_path', 'legends/')

        # temporary target dir for any Base64 encoded legend images
        # NOTE: this dir will be cleaned up automatically on reload
        self.images_temp_dir = None

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)
Beispiel #2
0
    def __init__(self, tenant, mail, app):
        """Constructor

        :param str tenant: Tenant ID
        :param flask_mail.Mail mail: Application mailer
        :param App app: Flask application
        """
        self.tenant = tenant
        self.mail = mail
        self.app = app
        self.logger = app.logger

        config_handler = RuntimeConfig("dbAuth", self.logger)
        config = config_handler.tenant_config(tenant)

        db_url = config.get('db_url')

        # get password constraints from config
        self.password_constraints = {
            'min_length': config.get('password_min_length', 8),
            'max_length': config.get('password_max_length', -1),
            'constraints': config.get('password_constraints', []),
            'min_constraints': config.get('password_min_constraints', 0),
            'constraints_message': config.get(
                'password_constraints_message',
                "Password does not match constraints"
            )
        }

        db_engine = DatabaseEngine()
        self.config_models = ConfigModels(db_engine, db_url)
        self.User = self.config_models.model('users')
Beispiel #3
0
    def __init__(self, tenant, logger):
        """Constructor

        :param str tenant: Tenant ID
        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("featureInfo", logger)
        config = config_handler.tenant_config(tenant)

        if config.get('default_info_template'):
            self.default_info_template = config.get('default_info_template')
        elif config.get('default_info_template_base64'):
            self.default_info_template = self.b64decode(
                config.get('default_info_template_base64'),
                default_info_template, "default info template"
            )
        else:
            self.default_info_template = default_info_template

        self.default_wms_url = config.get(
            'default_qgis_server_url', 'http://localhost:8001/ows/')
        self.data_service_url = config.get(
            'data_service_url', '/api/v1/data/').rstrip('/') + '/'

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)

        self.db_engine = DatabaseEngine()
Beispiel #4
0
    def __init__(self, tenant, db_engine, logger):
        self.tenant = tenant
        self._db_engine = db_engine
        self.logger = logger

        config_handler = RuntimeConfig("adminGui", logger)
        self._config = config_handler.tenant_config(tenant)
    def __init__(self, tenant, logger):
        """Constructor

        :param str tenant: Tenant ID
        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("mapViewer", logger)
        config = config_handler.tenant_config(tenant)

        # path to QWC2 files
        self.qwc2_path = config.get('qwc2_path', 'qwc2/')

        # QWC service URLs for config.json
        self.auth_service_url = self.__sanitize_url(
            config.get('auth_service_url'))
        self.ccc_config_service_url = self.__sanitize_url(
            config.get('ccc_config_service_url'))
        self.data_service_url = self.__sanitize_url(
            config.get('data_service_url'))
        self.dataproduct_service_url = self.__sanitize_url(
            config.get('dataproduct_service_url'))
        self.document_service_url = self.__sanitize_url(
            config.get('document_service_url',
                       config.get('feature_report_service_url')))
        self.elevation_service_url = self.__sanitize_url(
            config.get('elevation_service_url'))
        self.landreg_service_url = self.__sanitize_url(
            config.get('landreg_service_url'))
        self.mapinfo_service_url = self.__sanitize_url(
            config.get('mapinfo_service_url'))
        self.permalink_service_url = self.__sanitize_url(
            config.get('permalink_service_url'))
        self.plotinfo_service_url = self.__sanitize_url(
            config.get('plotinfo_service_url'))
        self.proxy_service_url = self.__sanitize_url(
            config.get('proxy_service_url'))
        self.search_service_url = self.__sanitize_url(
            config.get('search_service_url'))
        self.search_data_service_url = self.__sanitize_url(
            config.get('search_data_service_url'))
        # QWC service URLs for themes.json
        self.ogc_service_url = self.__sanitize_url(
            config.get('ogc_service_url', 'http://localhost:5013/'))
        self.info_service_url = self.__sanitize_url(
            config.get('info_service_url', self.ogc_service_url))
        self.legend_service_url = self.__sanitize_url(
            config.get('legend_service_url', self.ogc_service_url))
        self.print_service_url = self.__sanitize_url(
            config.get('print_service_url', self.ogc_service_url))

        # get config dir for tenant
        self.config_dir = os.path.dirname(
            RuntimeConfig.config_file_path('mapViewer', tenant))

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)
Beispiel #6
0
    def __init__(self, tenant, logger):
        """Constructor

        :param Logger logger: Application logger
        """
        self.logger = logger

        config_handler = RuntimeConfig("search", logger)
        config = config_handler.tenant_config(tenant)
        self.resources = self.load_resources(config)
        self.db_engine = DatabaseEngine()
        self.db = self.db_engine.db_engine(config.get('db_url'))
Beispiel #7
0
    def load_resources(self):
        """Load service resources from config."""
        # read config
        config_handler = RuntimeConfig("data", self.logger)
        config = config_handler.tenant_config(self.tenant)

        # get service resources
        datasets = {}
        for resource in config.resources().get('datasets', []):
            datasets[resource['name']] = resource

        return {
            'datasets': datasets
        }
    def put(self, dataset, id):
        """Update a dataset feature

        Update dataset feature with ID from a GeoJSON Feature and return it as
        a GeoJSON Feature.
        """
        config_handler = RuntimeConfig("data", app.logger)
        config = config_handler.tenant_config(tenant_handler.tenant())
        edit_user_field = config.get("edit_user_field", None)
        edit_timestamp_field = config.get("edit_timestamp_field", None)

        if request.is_json:
            # parse request data (NOTE: catches invalid JSON)
            feature = api.payload
            if isinstance(feature, dict):
                data_service = data_service_handler()
                internal_fields = {}
                if edit_user_field:
                    feature["properties"][edit_user_field] = get_auth_user()
                    internal_fields[edit_user_field] = {
                        'name': edit_user_field,
                        'data_type': 'text'
                    }
                if edit_timestamp_field:
                    feature["properties"][edit_timestamp_field] = str(
                        datetime.now())
                    internal_fields[edit_timestamp_field] = {
                        'name': edit_timestamp_field,
                        'data_type': 'text'
                    }

                result = data_service.update(get_auth_user(), dataset, id,
                                             feature, internal_fields)
                if 'error' not in result:
                    result['feature']['properties'] = dict(
                        filter(lambda x: x[0] not in internal_fields,
                               result['feature']['properties'].items()))
                    return result['feature']
                else:
                    error_code = result.get('error_code') or 404
                    error_details = result.get('error_details') or {}
                    api.abort(error_code, result['error'], **error_details)
            else:
                api.abort(400, "JSON is not an object")
        else:
            api.abort(400, "Request data is not JSON")
Beispiel #9
0
    def __init__(self, tenant, db_engine, logger):
        self.tenant = tenant
        self._db_engine = db_engine
        self.logger = logger

        config_handler = RuntimeConfig("adminGui", logger)
        try:
            self._config = config_handler.tenant_config(tenant)
        except FileNotFoundError:
            self._config = {
                "db_url":
                os.environ.get("DB_URL",
                               "postgresql:///?service=qwc_configdb"),
                "config_generator_service_url":
                os.environ.get("CONFIG_GENERATOR_SERVICE_URL",
                               "http://qwc-config-service:9090")
            }
    def get(self):
        """Submit query

        Returns additional information at clicked map position.
        """
        args = mapinfo_parser.parse_args()

        tenant = tenant_handler.tenant()
        config_handler = RuntimeConfig("mapinfo", app.logger)
        config = config_handler.tenant_config(tenant)

        db = db_engine.db_engine(config.get('db_url'))
        table = config.get('info_table')
        info_geom_col = config.get('info_geom_col')
        info_display_col = config.get('info_display_col')
        info_title = config.get('info_title')


        try:
            pos = args['pos'].split(',')
            pos = [float(pos[0]), float(pos[1])]
        except:
            return jsonify({"error": "Invalid position specified"})

        try:
            srid = int(re.match(r'epsg:(\d+)', args['crs'], re.IGNORECASE).group(1))
        except:
            return jsonify({"error": "Invalid projection specified"})

        conn = db.connect()

        sql = sql_text("""
            SELECT {display}
            FROM {table}
            WHERE ST_contains({table}.{geom}, ST_SetSRID(ST_Point(:x, :y), :srid))
            LIMIT 1;
        """.format(display=info_display_col, geom=info_geom_col, table=table))

        result = conn.execute(sql, x=pos[0], y=pos[1], srid=srid)
        info_result = []
        for row in result:
            info_result = [[info_title, row[info_display_col]]]

        conn.close()

        return jsonify({"results": info_result})
    def __init__(self, tenant, logger):
        """Constructor

        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("data", self.logger)
        config = config_handler.tenant_config(self.tenant)

        self.attachments_base_dir = config.get('attachments_base_dir',
                                               '/tmp/qwc_attachments/')
        self.max_file_size = int(
            config.get('max_attachment_file_size', 10 * 1024 * 1024))
        self.allowed_extensions = config.get('allowed_attachment_extensions',
                                             '').split(",")
Beispiel #12
0
    def __init__(self, tenant, logger):
        """Constructor

        :param Logger logger: Application logger
        """
        self.logger = logger
        self.tenant = tenant

        config_handler = RuntimeConfig("search", logger)
        config = config_handler.tenant_config(tenant)

        self.solr_service_url = config.get(
            'solr_service_url', 'http://localhost:8983/solr/gdi/select')
        self.word_split_re = re.compile(
            config.get('word_split_re', r'[\s,.:;"]+'))
        self.default_search_limit = config.get('search_result_limit', 50)

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)
Beispiel #13
0
    def get(self):
        """Get available land register templates"""

        tenant = tenant_handler.tenant()
        config_handler = RuntimeConfig("landreg", app.logger)
        config = config_handler.tenant_config(tenant)

        qgis_server_url = config.get('qgis_server_url')
        default_landreg_layout = config.get('default_landreg_layout')
        project = config.get('landreg_project')

        params = {
            "SERVICE": "WMS",
            "VERSION": "1.3.0",
            "REQUEST": "GetProjectSettings",
        }

        url = qgis_server_url.rstrip("/") + "/" + project
        req = requests.get(url, params=params)

        layouts = []
        try:
            capabilities = parseString(req.text)
            templates = capabilities.getElementsByTagName("WMS_Capabilities")[0]\
                                    .getElementsByTagName("Capability")[0]\
                                    .getElementsByTagName("ComposerTemplates")[0]
            for template in templates.getElementsByTagName("ComposerTemplate"):
                name = template.getAttribute("name")
                composerMap = template.getElementsByTagName("ComposerMap")[0]
                entry = {
                    "name": name,
                    "map": {
                        "width": float(composerMap.getAttribute("width")),
                        "height": float(composerMap.getAttribute("height")),
                        "name": composerMap.getAttribute("name")
                    },
                    "default": name == default_landreg_layout
                }
                layouts.append(entry)
        except:
            pass
        return jsonify(layouts)
Beispiel #14
0
    def __init__(self, tenant, mail, app):
        """Constructor

        :param str tenant: Tenant ID
        :param flask_mail.Mail mail: Application mailer
        :param App app: Flask application
        """
        self.tenant = tenant
        self.mail = mail
        self.app = app
        self.logger = app.logger

        config_handler = RuntimeConfig("dbAuth", self.logger)
        config = config_handler.tenant_config(tenant)

        db_url = config.get('db_url')

        db_engine = DatabaseEngine()
        self.config_models = ConfigModels(db_engine, db_url)
        self.User = self.config_models.model('users')
Beispiel #15
0
    def __init__(self, tenant, logger):
        """Constructor

        :param str tenant: Tenant ID
        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("ogc", logger)
        config = config_handler.tenant_config(tenant)

        # get internal QGIS server URL from config
        # (default: local qgis-server container)
        self.default_qgis_server_url = config.get(
            'default_qgis_server_url',
            'http://localhost:8001/ows/').rstrip('/') + '/'

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)
Beispiel #16
0
def load_dataset(tenant):
    config_handler = RuntimeConfig("elevation", app.logger)
    config = config_handler.tenant_config(tenant)

    dsfn = config.get('elevation_dataset')
    if dsfn is None:
        abort(Response('elevation_dataset undefined', 500))

    raster = gdal.Open(dsfn)
    if not raster:
        abort(Response('Failed to open dataset', 500))

    gtrans = raster.GetGeoTransform()
    if not gtrans:
        abort(Response('Failed to read dataset geotransform', 500))

    rasterSpatialRef = osr.SpatialReference()
    if rasterSpatialRef.ImportFromWkt(raster.GetProjectionRef()) != 0:
        abort(Response('Failed to parse dataset projection', 500))

    band = raster.GetRasterBand(1)
    if not band:
        abort(Response('Failed to open dataset raster band', 500))

    rasterUnitsToMeters = 1
    if band.GetUnitType() == "ft":
        rasterUnitsToMeters = 0.3048

    noDataValue = band.GetNoDataValue()
    if not noDataValue:
        noDataValue = None

    dataset = {
        "raster": raster,
        "band": band,
        "spatialRef": rasterSpatialRef,
        "geoTransform": gtrans,
        "unitsToMeters": rasterUnitsToMeters,
        "noDataValue": noDataValue
    }
    return dataset
Beispiel #17
0
    def __get_link(self, identity, program, path, args):
        tenant = tenant_handler.tenant()
        permissions_handler = PermissionsReader(tenant, app.logger)
        permitted_resources = permissions_handler.resource_permissions(
            'external_links', identity, program)
        if not permitted_resources:
            app.logger.warning(
                "Identity %s is not allowed to open link for program %s" %
                (identity, program))
            api.abort(404, 'Unable to open link')

        config_handler = RuntimeConfig("ext", app.logger)
        config = config_handler.tenant_config(tenant_handler.tenant())
        program_map = config.resources().get("external_links", [])
        link = None
        for entry in program_map:
            if entry["name"] == program:
                link = entry["url"]
                break
        if not link:
            app.logger.warning("No link configured for program %s" % (program))
            api.abort(404, 'Unable to open link')
        parts = parse.urlsplit(link)
        query = dict(parse.parse_qsl(parts.query))
        for key in query:
            query[key] = query[key].replace('$tenant$', tenant)
        query.update(args)
        parts = parts._replace(query=parse.urlencode(query))

        if path:
            parts = parts._replace(path=os.path.dirname(parts.path) + "/" +
                                   path)

        link = parts.geturl()
        api.logger.info("Proxying " + link)
        return link
Beispiel #18
0
    def post(self, dataset, id):
        """Update relation values for the specified dataset

        Return success status for each relation value.
        """
        args = post_relations_parser.parse_args()

        try:
            payload = json.loads(args['values'])
        except:
            payload = None
        if not isinstance(payload, dict):
            api.abort(400, "JSON is not an object")

        data_service = data_service_handler()

        config_handler = RuntimeConfig("data", app.logger)
        config = config_handler.tenant_config(tenant_handler.tenant())
        upload_user_field_suffix = config.get("upload_user_field_suffix", None)
        edit_user_field = config.get("edit_user_field", None)
        edit_timestamp_field = config.get("edit_timestamp_field", None)

        # Check if dataset with specified id exists
        if not data_service.is_editable(get_auth_user(), dataset, id):
            api.abort(404, "Dataset or feature not found or permission error")

        # Validate attachments
        attachments = attachments_service_handler()
        for key in request.files:
            filedata = request.files[key]
            attachment_valid, message = attachments.validate_attachment(
                dataset, filedata)
            if not attachment_valid:
                api.abort(
                    404,
                    "Attachment validation failed for " + key + ": " + message)

        # Save attachments
        saved_attachments = {}
        internal_fields = []
        for key in request.files:
            filedata = request.files[key]
            slug = attachments.save_attachment(dataset, filedata)
            if not slug:
                for slug in saved_attachments.values():
                    attachments.remove_attachment(dataset, slug)
                api.abort(404, "Failed to save attachment: " + key)
            else:
                saved_attachments[key] = slug
                parts = key.lstrip("file:").split("__")
                table = parts[0]
                field = parts[1]
                index = parts[2]
                payload[table]["records"][int(index)][
                    table + "__" + field] = "attachment://" + slug
                if upload_user_field_suffix:
                    upload_user_field = table + "__" + field + "__" + upload_user_field_suffix
                    payload[table]["records"][int(
                        index)][upload_user_field] = get_auth_user()
                    internal_fields.append(upload_user_field)

        ret = {}
        haserrors = False
        for (rel_table, rel_data) in payload.items():
            fk_field = rel_data.get("fk", None)
            ret[rel_table] = {"fk": fk_field, "records": []}
            tbl_prefix = rel_table + "__"
            for rel_record in rel_data.get("records", []):
                # Set foreign key for new records
                if rel_record.get("__status__", "") == "new":
                    rel_record[tbl_prefix + fk_field] = id

                if rel_record.get(tbl_prefix + fk_field, None) != id:
                    rel_record["__error__"] = "FK validation failed"
                    ret[rel_table]["records"].append(rel_record)
                    haserrors = True
                else:
                    entry = {
                        "type": "Feature",
                        "id": rel_record["id"] if "id" in rel_record else None,
                        "properties": {
                            k[len(tbl_prefix):]: v
                            for k, v in rel_record.items()
                            if k.startswith(tbl_prefix)
                        }
                    }

                    table_internal_fields = {
                        n[len(tbl_prefix):]: {
                            'name': n[len(tbl_prefix):],
                            'data_type': 'text'
                        }
                        for n in internal_fields if n.startswith(tbl_prefix)
                    }

                    if edit_user_field:
                        entry["properties"][edit_user_field] = get_auth_user()
                        table_internal_fields[edit_user_field] = {
                            'name': edit_user_field,
                            'data_type': 'text'
                        }
                    if edit_timestamp_field:
                        entry["properties"][edit_timestamp_field] = str(
                            datetime.now())
                        table_internal_fields[edit_timestamp_field] = {
                            'name': edit_timestamp_field,
                            'data_type': 'text'
                        }

                    if not "__status__" in rel_record:
                        ret[rel_table]["records"].append(rel_record)
                        continue
                    elif rel_record["__status__"] == "new":
                        result = data_service.create(get_auth_user(),
                                                     rel_table, entry,
                                                     table_internal_fields)
                    elif rel_record["__status__"] == "changed":
                        (newattachments,
                         oldattachments) = self.attachments_diff(
                             data_service, attachments, dataset, rel_table,
                             rel_record["id"], entry, table_internal_fields,
                             upload_user_field_suffix)
                        result = data_service.update(get_auth_user(),
                                                     rel_table,
                                                     rel_record["id"], entry,
                                                     table_internal_fields)
                        self.cleanup_attachments(
                            attachments, dataset, newattachments
                            if "error" in result else oldattachments)
                    elif rel_record["__status__"].startswith("deleted"):
                        (newattachments,
                         oldattachments) = self.attachments_diff(
                             data_service, attachments, dataset, rel_table,
                             rel_record["id"], entry, table_internal_fields,
                             upload_user_field_suffix, True)
                        if upload_user_field_suffix:
                            data_service.update(get_auth_user(), rel_table,
                                                rel_record["id"], entry,
                                                table_internal_fields)
                        result = data_service.destroy(get_auth_user(),
                                                      rel_table,
                                                      rel_record["id"])
                        self.cleanup_attachments(
                            attachments, dataset, newattachments
                            if "error" in result else oldattachments)
                    else:
                        continue
                    if "error" in result:
                        rel_record["error"] = result["error"]
                        rel_record["error_details"] = result.get(
                            'error_details') or {}
                        ret[rel_table]["records"].append(rel_record)
                        haserrors = True
                    elif "feature" in result:
                        rel_record = {(rel_table + "__" + k): v
                                      for k, v in result['feature']
                                      ['properties'].items()
                                      if not k in table_internal_fields}
                        rel_record["id"] = result['feature']["id"]
                        ret[rel_table]["records"].append(rel_record)

        return {"relationvalues": ret, "success": not haserrors}
Beispiel #19
0
    def put(self, dataset, id):
        """Update a dataset feature

        Update dataset feature with ID from a GeoJSON Feature and return it as
        a GeoJSON Feature.
        """
        args = feature_multipart_parser.parse_args()
        try:
            feature = json.loads(args['feature'])
        except:
            feature = None
        if not isinstance(feature, dict):
            api.abort(400, "feature is not an object")

        config_handler = RuntimeConfig("data", app.logger)
        config = config_handler.tenant_config(tenant_handler.tenant())
        upload_user_field_suffix = config.get("upload_user_field_suffix", None)
        edit_user_field = config.get("edit_user_field", None)
        edit_timestamp_field = config.get("edit_timestamp_field", None)

        # Validate attachments
        attachments = attachments_service_handler()
        for key in request.files:
            filedata = request.files[key]
            attachment_valid, message = attachments.validate_attachment(
                dataset, filedata)
            if not attachment_valid:
                api.abort(
                    404,
                    "Attachment validation failed for " + key + ": " + message)

        # Save attachments
        saved_attachments = {}
        internal_fields = {}
        for key in request.files:
            filedata = request.files[key]
            slug = attachments.save_attachment(dataset, filedata)
            if not slug:
                for slug in saved_attachments.values():
                    attachments.remove_attachment(dataset, slug)
                api.abort(404, "Failed to save attachment: " + key)
            else:
                saved_attachments[key] = slug
                field = key.lstrip("file:")
                feature["properties"][field] = "attachment://" + slug
                if upload_user_field_suffix:
                    upload_user_field = field + "__" + upload_user_field_suffix
                    feature["properties"][upload_user_field] = get_auth_user()
                    internal_fields[upload_user_field] = {
                        'name': upload_user_field,
                        'data_type': 'text'
                    }

        data_service = data_service_handler()

        prev = data_service.show(get_auth_user(), dataset, id, None)
        if prev:
            prev_feature = prev["feature"]
            # If a non-empty attachment field value is changed, delete the attachment
            keys = list(feature["properties"].keys())
            for key in keys:
                if key in prev_feature["properties"] and prev_feature[
                        "properties"][key] and str(
                            prev_feature["properties"][key]).startswith(
                                "attachment://") and feature["properties"][
                                    key] != prev_feature["properties"][key]:
                    attachments.remove_attachment(
                        dataset, prev_feature["properties"][key].lstrip(
                            "attachment://"))
                    if upload_user_field_suffix:
                        upload_user_field = key + "__" + upload_user_field_suffix
                        feature["properties"][
                            upload_user_field] = get_auth_user()
                        internal_fields[upload_user_field] = {
                            'name': upload_user_field,
                            'data_type': 'text'
                        }

        if edit_user_field:
            feature["properties"][edit_user_field] = get_auth_user()
            internal_fields[edit_user_field] = {
                'name': edit_user_field,
                'data_type': 'text'
            }
        if edit_timestamp_field:
            feature["properties"][edit_timestamp_field] = str(datetime.now())
            internal_fields[edit_timestamp_field] = {
                'name': edit_timestamp_field,
                'data_type': 'text'
            }

        result = data_service.update(get_auth_user(), dataset, id, feature,
                                     internal_fields)

        if 'error' not in result:
            result['feature']['properties'] = dict(
                filter(lambda x: x[0] not in internal_fields,
                       result['feature']['properties'].items()))
            return result['feature']
        else:
            for slug in saved_attachments.values():
                attachments.remove_attachment(dataset, slug)
            error_code = result.get('error_code') or 404
            error_details = result.get('error_details') or {}
            api.abort(error_code, result['error'], **error_details)
Beispiel #20
0
    def post(self):
        """Submit query

        Return map print
        """
        post_params = dict(
            urlparse.parse_qsl(request.get_data().decode('utf-8')))
        app.logger.info("POST params: %s" % post_params)

        tenant = tenant_handler.tenant()
        config_handler = RuntimeConfig("landreg", app.logger)
        config = config_handler.tenant_config(tenant)

        db = db_engine.db_engine(config.get('db_url'))
        qgis_server_url = config.get('qgis_server_url')
        project = config.get('landreg_project')
        landreg_printinfo_table = config.get('landreg_printinfo_table')
        landreg_print_layers = config.get('landreg_print_layers')

        params = {
            "SERVICE": "WMS",
            "VERSION": "1.3.0",
            "REQUEST": "GetPrint",
            "FORMAT": "PDF"
        }
        params.update(post_params)

        # Normalize parameter keys to upper case
        params = {k.upper(): v for k, v in params.items()}

        # Set LAYERS and OPACITIES
        params["LAYERS"] = landreg_print_layers
        params["OPACITIES"] = ",".join(
            map(lambda item: "255", params["LAYERS"].split(",")))

        # Determine center of extent
        extent = list(map(lambda x: float(x), params["EXTENT"].split(",")))
        x = 0.5 * (extent[0] + extent[2])
        y = 0.5 * (extent[1] + extent[3])

        # Determine lieferdatum and nfgeometer
        conn = db.connect()
        sql = sql_text("""
            SELECT nfgeometer, lieferdatum, anschrift, kontakt, gemeinde
            FROM {table}
            WHERE ST_CONTAINS(geometrie, ST_SetSRID(ST_MakePoint(:x, :y), 2056));
        """.format(table=landreg_printinfo_table))

        sql_result = conn.execute(sql, x=x, y=y).fetchone()

        if sql_result:
            params["NFGEOMETER"] = sql_result["nfgeometer"]
            params["LIEFERDATUM"] = sql_result["lieferdatum"]
            params["ANSCHRIFT"] = sql_result["anschrift"]
            params["KONTAKT"] = sql_result["kontakt"]
            params["GEMEINDE"] = sql_result["gemeinde"]

        conn.close()

        # Prefix params with composer map name: Extent, scale, rotation
        params["map0:EXTENT"] = params["EXTENT"]
        del params["EXTENT"]
        params["map0:SCALE"] = params["SCALE"]
        del params["SCALE"]
        params["map0:ROTATION"] = params["ROTATION"]
        del params["ROTATION"]
        if "GRID_INTERVAL_X" in params:
            params["map0:GRID_INTERVAL_X"] = params["GRID_INTERVAL_X"]
            del params["GRID_INTERVAL_X"]
        if "GRID_INTERVAL_Y" in params:
            params["map0:GRID_INTERVAL_Y"] = params["GRID_INTERVAL_Y"]
            del params["GRID_INTERVAL_Y"]

        # Forward to QGIS server
        url = qgis_server_url.rstrip("/") + "/" + project
        req = requests.post(url, timeout=120, data=params)
        app.logger.info("Forwarding request to %s\n%s" % (req.url, params))

        response = Response(stream_with_context(
            req.iter_content(chunk_size=1024)),
                            status=req.status_code)
        response.headers['content-type'] = req.headers['content-type']
        if req.headers['content-type'] == 'application/pdf':
            response.headers['content-disposition'] = \
                'attachment; filename=' + project + '.' + params['FORMAT'].lower()

        return response
Beispiel #21
0
    def __init__(self, tenant, logger):
        """Constructor

        :param str tenant: Tenant ID
        :param Logger logger: Application logger
        """
        self.tenant = tenant
        self.logger = logger

        config_handler = RuntimeConfig("mapViewer", logger)
        config = config_handler.tenant_config(tenant)

        # path to QWC2 files
        self.qwc2_path = config.get('qwc2_path', 'qwc2/')

        # QWC service URLs for config.json
        self.auth_service_url = self.__sanitize_url(
            config.get('auth_service_url'))
        self.ccc_config_service_url = self.__sanitize_url(
            config.get('ccc_config_service_url'))
        self.data_service_url = self.__sanitize_url(
            config.get('data_service_url'))
        self.dataproduct_service_url = self.__sanitize_url(
            config.get('dataproduct_service_url'))
        self.document_service_url = self.__sanitize_url(
            config.get('document_service_url',
                       config.get('feature_report_service_url')))
        self.elevation_service_url = self.__sanitize_url(
            config.get('elevation_service_url'))
        self.landreg_service_url = self.__sanitize_url(
            config.get('landreg_service_url'))
        self.mapinfo_service_url = self.__sanitize_url(
            config.get('mapinfo_service_url'))
        self.permalink_service_url = self.__sanitize_url(
            config.get('permalink_service_url'))
        self.plotinfo_service_url = self.__sanitize_url(
            config.get('plotinfo_service_url'))
        self.proxy_service_url = self.__sanitize_url(
            config.get('proxy_service_url'))
        self.search_service_url = self.__sanitize_url(
            config.get('search_service_url'))
        self.search_data_service_url = self.__sanitize_url(
            config.get('search_data_service_url'))
        # QWC service URLs for themes.json
        self.ogc_service_url = self.__sanitize_url(
            config.get('ogc_service_url', 'http://localhost:5013/'))
        self.info_service_url = self.__sanitize_url(
            config.get('info_service_url', self.ogc_service_url))
        self.legend_service_url = self.__sanitize_url(
            config.get('legend_service_url', self.ogc_service_url))
        self.print_service_url = self.__sanitize_url(
            config.get('print_service_url', self.ogc_service_url))

        self.show_restricted_themes = config.get('show_restricted_themes', False)
        self.show_restricted_themes_whitelist = config.get('show_restricted_themes_whitelist', "")

        # get config dir for tenant
        self.config_dir = os.path.dirname(
            RuntimeConfig.config_file_path('mapViewer', tenant)
        )

        # temporary target dir for any Base64 encoded thumbnail images
        # NOTE: this dir will be cleaned up automatically on reload
        self.images_temp_dir = None

        self.resources = self.load_resources(config)
        self.permissions_handler = PermissionsReader(tenant, logger)