Example #1
0
    def test_importer_configuration(self):
        database_settings = self.DATABASE_DEFAULT_SETTINGS.copy()
        ogc_server_settings = self.OGC_DEFAULT_SETTINGS.copy()
        uploader_settings = self.UPLOADER_DEFAULT_SETTINGS.copy()

        uploader_settings['BACKEND'] = 'geonode.importer'
        self.assertTrue(['geonode_imports' not in database_settings.keys()])

        # Test the importer backend without specifying a datastore or
        # corresponding database.
        with self.settings(UPLOADER=uploader_settings, OGC_SERVER=ogc_server_settings, DATABASES=database_settings):
            OGC_Servers_Handler(ogc_server_settings)['default']

        ogc_server_settings['default']['DATASTORE'] = 'geonode_imports'

        # Test the importer backend with a datastore but no corresponding
        # database.
        with self.settings(UPLOADER=uploader_settings, OGC_SERVER=ogc_server_settings, DATABASES=database_settings):
            OGC_Servers_Handler(ogc_server_settings)['default']

        database_settings['geonode_imports'] = database_settings[
            'default'].copy()
        database_settings['geonode_imports'].update(
            {'NAME': 'geonode_imports'})

        # Test the importer backend with a datastore and a corresponding
        # database, no exceptions should be thrown.
        with self.settings(UPLOADER=uploader_settings, OGC_SERVER=ogc_server_settings, DATABASES=database_settings):
            OGC_Servers_Handler(ogc_server_settings)['default']
Example #2
0
    def test_ogc_server_settings(self):
        """
        Tests the OGC Servers Handler class.
        """

        with override_settings(OGC_SERVER=self.OGC_DEFAULT_SETTINGS,
                               UPLOADER=self.UPLOADER_DEFAULT_SETTINGS):
            OGC_SERVER = self.OGC_DEFAULT_SETTINGS.copy()
            OGC_SERVER.update(
                {'PUBLIC_LOCATION': 'http://localhost:8080/geoserver/'})

            ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']

            default = OGC_SERVER.get('default')
            self.assertEqual(ogc_settings.server, default)
            self.assertEqual(ogc_settings.BACKEND, default.get('BACKEND'))
            self.assertEqual(ogc_settings.LOCATION, default.get('LOCATION'))
            self.assertEqual(ogc_settings.PUBLIC_LOCATION,
                             default.get('PUBLIC_LOCATION'))
            self.assertEqual(ogc_settings.USER, default.get('USER'))
            self.assertEqual(ogc_settings.PASSWORD, default.get('PASSWORD'))
            self.assertEqual(ogc_settings.DATASTORE, str())
            self.assertEqual(ogc_settings.credentials, ('admin', 'geoserver'))
            self.assertTrue(ogc_settings.MAPFISH_PRINT_ENABLED)
            self.assertTrue(ogc_settings.PRINT_NG_ENABLED)
            self.assertTrue(ogc_settings.GEONODE_SECURITY_ENABLED)
            self.assertFalse(ogc_settings.GEOGIG_ENABLED)
            self.assertFalse(ogc_settings.WMST_ENABLED)
            self.assertTrue(ogc_settings.BACKEND_WRITE_ENABLED)
            self.assertFalse(ogc_settings.WPS_ENABLED)
Example #3
0
def create_gs_thumbnail_geonode(instance, overwrite=False, check_bbox=False):
    """
    Create a thumbnail with a GeoServer request.
    """
    ogc_server_settings = OGC_Servers_Handler(settings.OGC_SERVER)["default"]
    wms_version = getattr(ogc_server_settings, "WMS_VERSION") or "1.1.1"

    create_thumbnail(
        instance,
        wms_version=wms_version,
        overwrite=overwrite,
    )
Example #4
0
    def test_ogc_server_defaults(self):
        """
        Tests that OGC_SERVER_SETTINGS are built if they do not exist in the settings.
        """

        OGC_SERVER = {'default': dict()}

        defaults = self.OGC_DEFAULT_SETTINGS.get('default')
        ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']
        self.assertEqual(ogc_settings.server, defaults)
        self.assertEqual(ogc_settings.rest, defaults['LOCATION'] + 'rest')
        self.assertEqual(ogc_settings.ows, defaults['LOCATION'] + 'ows')

        # Make sure we get None vs a KeyError when the key does not exist
        self.assertIsNone(ogc_settings.SFDSDFDSF)
Example #5
0
    def test_ogc_server_defaults(self):
        """
        Tests that OGC_SERVER_SETTINGS are built if they do not exist in the settings.
        """

        OGC_SERVER = {'default': dict()}

        defaults = self.OGC_DEFAULT_SETTINGS.get('default')
        ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']
        self.assertEqual(ogc_settings.server, defaults)
        self.assertEqual(ogc_settings.rest, defaults['LOCATION'] + 'rest')
        self.assertEqual(ogc_settings.ows, defaults['LOCATION'] + 'ows')

        # Make sure we get None vs a KeyError when the key does not exist
        self.assertIsNone(ogc_settings.SFDSDFDSF)

        # Testing OWS endpoints
        from urlparse import urljoin
        from django.core.urlresolvers import reverse
        from .ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities
        wcs = _wcs_get_capabilities()
        logger.debug(wcs)
        self.assertIsNotNone(wcs)

        try:
            wcs_url = urljoin(settings.SITEURL, reverse('wcs_endpoint'))
        except BaseException:
            wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertEquals(
            wcs,
            '%s?version=2.0.1&request=GetCapabilities&service=WCS' % wcs_url)

        wfs = _wfs_get_capabilities()
        logger.debug(wfs)
        self.assertIsNotNone(wfs)

        try:
            wfs_url = urljoin(settings.SITEURL, reverse('wfs_endpoint'))
        except BaseException:
            wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertEquals(
            wfs,
            '%s?version=1.1.0&request=GetCapabilities&service=WFS' % wfs_url)

        wms = _wms_get_capabilities()
        logger.debug(wms)
        self.assertIsNotNone(wms)

        try:
            wms_url = urljoin(settings.SITEURL, reverse('wms_endpoint'))
        except BaseException:
            wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertEquals(
            wms,
            '%s?version=1.1.1&request=GetCapabilities&service=WMS' % wms_url)

        # Test OWS Download Links
        import urllib
        from geonode.geoserver.ows import wcs_links, wfs_links, wms_links
        instance = Layer.objects.all()[0]
        bbox = instance.bbox
        srid = instance.srid
        height = 512
        width = 512

        # WMS Links
        wms_links = wms_links(ogc_settings.public_url + 'wms?',
                              instance.alternate.encode('utf-8'), bbox, srid,
                              height, width)
        self.assertIsNotNone(wms_links)
        self.assertEquals(len(wms_links), 3)
        wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wms')
        identifier = urllib.urlencode(
            {'layers': instance.alternate.encode('utf-8')})
        for _link in wms_links:
            logger.debug('%s --> %s' % (wms_url, _link[3]))
            self.assertTrue(wms_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WFS Links
        wfs_links = wfs_links(ogc_settings.public_url + 'wfs?',
                              instance.alternate.encode('utf-8'), bbox, srid)
        self.assertIsNotNone(wfs_links)
        self.assertEquals(len(wfs_links), 6)
        wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wfs')
        identifier = urllib.urlencode(
            {'typename': instance.alternate.encode('utf-8')})
        for _link in wfs_links:
            logger.debug('%s --> %s' % (wfs_url, _link[3]))
            self.assertTrue(wfs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WCS Links
        wcs_links = wcs_links(ogc_settings.public_url + 'wcs?',
                              instance.alternate.encode('utf-8'), bbox, srid)
        self.assertIsNotNone(wcs_links)
        self.assertEquals(len(wcs_links), 2)
        wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wcs')
        identifier = urllib.urlencode(
            {'coverageid': instance.alternate.encode('utf-8')})
        for _link in wcs_links:
            logger.debug('%s --> %s' % (wcs_url, _link[3]))
            self.assertTrue(wcs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])
Example #6
0
def _layers_locations(
    instance: Union[Layer, Map], compute_bbox: bool = False, target_crs: str = "EPSG:3857"
) -> Tuple[List[List], List]:
    """
    Function returning a list mapping instance's layers to their locations, enabling to construct a minimum
    number of  WMS request for multiple layers of the same OGC source (ensuring layers order for Maps)

    :param instance: instance of Layer or Map models
    :param compute_bbox: flag determining whether a BBOX containing the instance should be computed,
                         based on instance's layers
    :param target_crs: valid only when compute_bbox is True - CRS of the returned BBOX
    :return: a tuple with a list, which maps layers to their locations in a correct layers order
             e.g.
                [
                    ["http://localhost:8080/geoserver/": ["geonode:layer1", "geonode:layer2]]
                ]
             and a list optionally consisting of 5 elements containing west, east, south, north
             instance's boundaries and CRS
    """
    ogc_server_settings = OGC_Servers_Handler(settings.OGC_SERVER)["default"]

    locations = []
    bbox = []

    if isinstance(instance, Layer):

        # for local layers
        if instance.remote_service is None:
            locations.append([ogc_server_settings.LOCATION, [instance.alternate]])
        # for remote layers
        else:
            locations.append([instance.remote_service.service_url, [instance.alternate]])

        if compute_bbox:
            # handle exceeding the area of use of the default thumb's CRS
            if (
                    instance.bbox[-1].upper() != 'EPSG:3857'
                    and target_crs.upper() == 'EPSG:3857'
                    and utils.exceeds_epsg3857_area_of_use(instance.bbox)
            ):
                bbox = utils.transform_bbox(utils.crop_to_3857_area_of_use(instance.bbox), target_crs.lower())
            else:
                bbox = utils.transform_bbox(instance.bbox, target_crs.lower())

    elif isinstance(instance, Map):

        map_layers = instance.layers.copy()
        # ensure correct order of layers in the map (higher stack_order are printed on top of lower)
        map_layers.sort(key=lambda l: l.stack_order)

        for map_layer in map_layers:

            if not map_layer.visibility:
                logger.debug("Skipping not visible layer in the thumbnail generation.")
                continue

            if not map_layer.local and not map_layer.ows_url:
                logger.warning(
                    "Incorrectly defined remote layer encountered (no OWS URL defined)."
                    "Skipping it in the thumbnail generation."
                )
                continue

            name = get_layer_name(map_layer)
            store = map_layer.store
            workspace = get_layer_workspace(map_layer)

            if store and Layer.objects.filter(store=store, workspace=workspace, name=name).count() > 0:
                layer = Layer.objects.filter(store=store, workspace=workspace, name=name).first()

            elif workspace and Layer.objects.filter(workspace=workspace, name=name).count() > 0:
                layer = Layer.objects.filter(workspace=workspace, name=name).first()

            elif Layer.objects.filter(alternate=map_layer.name).count() > 0:
                layer = Layer.objects.filter(alternate=map_layer.name).first()

            else:
                logger.warning(f"Layer for MapLayer {name} was not found. Skipping it in the thumbnail.")
                continue

            if layer.storetype in ['tileStore', 'remote']:
                # limit number of locations, ensuring layer order
                if len(locations) and locations[-1][0] == layer.remote_service.service_url:
                    # if previous layer's location is the same as the current one - append current layer there
                    locations[-1][1].append(layer.alternate)
                else:
                    locations.append([layer.remote_service.service_url, [layer.alternate]])
            else:
                # limit number of locations, ensuring layer order
                if len(locations) and locations[-1][0] == settings.OGC_SERVER["default"]["LOCATION"]:
                    # if previous layer's location is the same as the current one - append current layer there
                    locations[-1][1].append(layer.alternate)
                else:
                    locations.append([settings.OGC_SERVER["default"]["LOCATION"], [layer.alternate]])

            if compute_bbox:
                # handle exceeding the area of use of the default thumb's CRS
                if (
                        layer.bbox[-1].upper() != 'EPSG:3857'
                        and target_crs.upper() == 'EPSG:3857'
                        and utils.exceeds_epsg3857_area_of_use(layer.bbox)
                ):
                    layer_bbox = utils.transform_bbox(utils.crop_to_3857_area_of_use(layer.bbox), target_crs.lower())
                else:
                    layer_bbox = utils.transform_bbox(layer.bbox, target_crs.lower())

                if not bbox:
                    bbox = layer_bbox
                else:
                    # layer's BBOX: (left, right, bottom, top)
                    bbox = [
                        min(bbox[0], layer_bbox[0]),
                        max(bbox[1], layer_bbox[1]),
                        min(bbox[2], layer_bbox[2]),
                        max(bbox[3], layer_bbox[3]),
                    ]

    if bbox and len(bbox) < 5:
        bbox = list(bbox) + [target_crs]  # convert bbox to list, if it's tuple

    return locations, bbox
from django.contrib.gis.gdal import CoordTransform, SpatialReference
from django.contrib.gis.geos import GEOSGeometry, Point
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
from lxml import etree
from requests import Request

from geonode import qgis_server
from geonode.geoserver.helpers import OGC_Servers_Handler
from geonode.layers.models import Layer
from geonode.qgis_server.gis_tools import num2deg
from geonode.qgis_server.models import (QGISServerLayer, QGISServerMap,
                                        QGISServerStyle)

logger = logging.getLogger("geonode.qgis_server.helpers")
ogc_server_settings = OGC_Servers_Handler(settings.OGC_SERVER)['default']


def validate_django_settings():
    """Check that settings file configured correctly for qgis_server backend.
    """
    # geonode.qgis_server must exists in INSTALLED_APPS and not geoserver
    if 'geonode.qgis_server' not in settings.INSTALLED_APPS:
        raise ImproperlyConfigured(
            'geonode.qgis_server module not included in INSTALLED_APPS.')
    if 'geonode.geoserver' in settings.INSTALLED_APPS:
        raise ImproperlyConfigured(
            'You want to use QGIS Server backend, but geonode.geoserver module'
            ' is still included in INSTALLED_APPS.')

    # LOCAL_GEOSERVER settings should not exists
Example #8
0
def get_map(
    ogc_server_location: str,
    layers: List,
    bbox: List,
    wms_version: str = settings.OGC_SERVER["default"].get(
        "WMS_VERSION", "1.1.1"),
    mime_type: str = "image/png",
    styles: List = None,
    width: int = 240,
    height: int = 200,
    max_retries: int = 3,
    retry_delay: int = 1,
):
    """
    Function fetching an image from OGC server.
    For the requests to the configured OGC backend (ogc_server_settings.LOCATION) the function tries to generate
    an access_token and attach it to the URL.
    If access_token is not added ant the request is against Geoserver Basic Authentication is used instead.
    If image retrieval fails, function retries to fetch the image max_retries times, waiting
    retry_delay seconds between consecutive requests.

    :param ogc_server_location: OGC server URL
    :param layers: layers which should be fetched from the OGC server
    :param bbox: area's bounding box in format: [west, east, south, north, CRS]
    :param wms_version: WMS version of the query (default: 1.1.1)
    :param mime_type: mime type of the returned image
    :param styles: styles, which OGC server should use for rendering an image
    :param width: width of the returned image
    :param height: height of the returned image
    :param max_retries: maximum number of retries before skipping retrieval
    :param retry_delay: number of seconds waited between retries
    :returns: retrieved image
    """

    ogc_server_settings = OGC_Servers_Handler(settings.OGC_SERVER)["default"]

    if ogc_server_location is not None:
        thumbnail_url = ogc_server_location
    else:
        thumbnail_url = ogc_server_settings.LOCATION

    wms_endpoint = ""
    additional_kwargs = {}
    if thumbnail_url == ogc_server_settings.LOCATION:
        # add access token to requests to Geoserver (logic based on the previous implementation)
        username = ogc_server_settings.credentials.username
        user = get_user_model().objects.filter(username=username).first()
        if user:
            access_token = get_or_create_token(user)
            if access_token and not access_token.is_expired():
                additional_kwargs['access_token'] = access_token.token

        # add WMS endpoint to requests to Geoserver
        wms_endpoint = getattr(ogc_server_settings, "WMS_ENDPOINT") or "ows"

    # prepare authorization for WMS service
    headers = {}
    if "access_token" not in additional_kwargs.keys():
        if thumbnail_url.startswith(
                settings.OGC_SERVER["default"]["LOCATION"]):
            # for the Geoserver backend, use Basic Auth, if access_token is not provided
            _user = settings.OGC_SERVER["default"].get("USER")
            _pwd = settings.OGC_SERVER["default"].get("PASSWORD")
            encoded_credentials = base64.b64encode(
                f"{_user}:{_pwd}".encode("UTF-8")).decode("ascii")
            headers["Authorization"] = f"Basic {encoded_credentials}"

    wms = WebMapService(f"{thumbnail_url}{wms_endpoint}",
                        version=wms_version,
                        headers=headers)

    image = None
    for retry in range(max_retries):
        try:
            # fetch data
            image = wms.getmap(
                layers=layers,
                styles=styles,
                srs=bbox[-1],
                bbox=[bbox[0], bbox[2], bbox[1], bbox[3]],
                size=(width, height),
                format=mime_type,
                transparent=True,
                timeout=getattr(ogc_server_settings, "TIMEOUT", None),
                **additional_kwargs,
            )

            # validate response
            if not image or "ServiceException" in str(image.read()):
                raise ThumbnailError(
                    f"Fetching partial thumbnail from {thumbnail_url} failed with response: {str(image)}"
                )

        except Exception as e:
            if retry + 1 >= max_retries:
                logger.exception(e)
                return

            time.sleep(retry_delay)
            continue
        else:
            break

    return image.read()
Example #9
0
    def test_ogc_server_defaults(self):
        """
        Tests that OGC_SERVER_SETTINGS are built if they do not exist in the settings.
        """
        from django.urls import reverse, resolve
        from ..ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities

        OGC_SERVER = {'default': dict()}

        defaults = self.OGC_DEFAULT_SETTINGS.get('default')
        ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']
        self.assertEqual(ogc_settings.server, defaults)
        self.assertEqual(ogc_settings.rest, defaults['LOCATION'] + 'rest')
        self.assertEqual(ogc_settings.ows, defaults['LOCATION'] + 'ows')

        # Make sure we get None vs a KeyError when the key does not exist
        self.assertIsNone(ogc_settings.SFDSDFDSF)

        # Testing REST endpoints
        route = resolve('/gs/rest/layers').route
        self.assertEqual(route, '^gs/rest/layers')

        route = resolve('/gs/rest/imports').route
        self.assertEqual(route, '^gs/rest/imports')

        route = resolve('/gs/rest/sldservice').route
        self.assertEqual(route, '^gs/rest/sldservice')

        store_resolver = resolve('/gs/rest/stores/geonode_data/')
        self.assertEqual(store_resolver.url_name, 'stores')
        self.assertEqual(store_resolver.kwargs['store_type'], 'geonode_data')
        self.assertEqual(store_resolver.route, '^gs/rest/stores/(?P<store_type>\\w+)/$')

        sld_resolver = resolve('/gs/rest/styles')
        self.assertIsNone(sld_resolver.url_name)
        self.assertTrue('workspace' not in sld_resolver.kwargs)
        self.assertEqual(sld_resolver.kwargs['proxy_path'], '/gs/rest/styles')
        self.assertEqual(sld_resolver.kwargs['downstream_path'], 'rest/styles')
        self.assertEqual(sld_resolver.route, '^gs/rest/styles')

        sld_resolver = resolve('/gs/rest/workspaces/geonode/styles')
        self.assertIsNone(sld_resolver.url_name)
        self.assertEqual(sld_resolver.kwargs['workspace'], 'geonode')
        self.assertEqual(sld_resolver.kwargs['proxy_path'], '/gs/rest/workspaces')
        self.assertEqual(sld_resolver.kwargs['downstream_path'], 'rest/workspaces')
        self.assertEqual(sld_resolver.route, '^gs/rest/workspaces/(?P<workspace>\\w+)')

        # Testing OWS endpoints
        wcs = _wcs_get_capabilities()
        logger.debug(wcs)
        self.assertIsNotNone(wcs)

        try:
            wcs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except Exception:
            wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')

        self.assertTrue(wcs.startswith(wcs_url))
        self.assertIn("service=WCS", wcs)
        self.assertIn("request=GetCapabilities", wcs)
        self.assertIn("version=2.0.1", wcs)

        wfs = _wfs_get_capabilities()
        logger.debug(wfs)
        self.assertIsNotNone(wfs)

        try:
            wfs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except Exception:
            wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wfs.startswith(wfs_url))
        self.assertIn("service=WFS", wfs)
        self.assertIn("request=GetCapabilities", wfs)
        self.assertIn("version=1.1.0", wfs)

        wms = _wms_get_capabilities()
        logger.debug(wms)
        self.assertIsNotNone(wms)

        try:
            wms_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except Exception:
            wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wms.startswith(wms_url))
        self.assertIn("service=WMS", wms)
        self.assertIn("request=GetCapabilities", wms)
        self.assertIn("version=1.3.0", wms)

        # Test OWS Download Links
        from geonode.geoserver.ows import wcs_links, wfs_links, wms_links
        instance = Layer.objects.all()[0]
        bbox = instance.bbox
        srid = instance.srid
        height = 512
        width = 512

        # Default Style (expect exception since we are offline)
        try:
            style = get_sld_for(gs_catalog, instance)
        except Exception:
            style = gs_catalog.get_style("line")
        self.assertIsNotNone(style)
        instance.default_style, _ = Style.objects.get_or_create(
            name=style.name,
            defaults=dict(
                sld_title=style.sld_title,
                sld_body=style.sld_body
            )
        )
        self.assertIsNotNone(instance.default_style)
        self.assertIsNotNone(instance.default_style.name)

        # WMS Links
        wms_links = wms_links(ogc_settings.public_url + 'wms?',
                              instance.alternate,
                              bbox,
                              srid,
                              height,
                              width)
        self.assertIsNotNone(wms_links)
        self.assertEqual(len(wms_links), 3)
        wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wms')
        identifier = urlencode({'layers': instance.alternate})
        for _link in wms_links:
            logger.debug(f'{wms_url} --> {_link[3]}')
            self.assertTrue(wms_url in _link[3])
            logger.debug(f'{identifier} --> {_link[3]}')
            self.assertTrue(identifier in _link[3])

        # WFS Links
        wfs_links = wfs_links(ogc_settings.public_url + 'wfs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wfs_links)
        self.assertEqual(len(wfs_links), 6)
        wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wfs')
        identifier = urlencode({'typename': instance.alternate})
        for _link in wfs_links:
            logger.debug(f'{wfs_url} --> {_link[3]}')
            self.assertTrue(wfs_url in _link[3])
            logger.debug(f'{identifier} --> {_link[3]}')
            self.assertTrue(identifier in _link[3])

        # WCS Links
        wcs_links = wcs_links(ogc_settings.public_url + 'wcs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wcs_links)
        self.assertEqual(len(wcs_links), 2)
        wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wcs')
        identifier = urlencode({'coverageid': instance.alternate.replace(':', '__', 1)})
        for _link in wcs_links:
            logger.debug(f'{wcs_url} --> {_link[3]}')
            self.assertTrue(wcs_url in _link[3])
            logger.debug(f'{identifier} --> {_link[3]}')
            self.assertTrue(identifier in _link[3])
Example #10
0
    def test_ogc_server_defaults(self):
        """
        Tests that OGC_SERVER_SETTINGS are built if they do not exist in the settings.
        """

        OGC_SERVER = {'default': dict()}

        defaults = self.OGC_DEFAULT_SETTINGS.get('default')
        ogc_settings = OGC_Servers_Handler(OGC_SERVER)['default']
        self.assertEqual(ogc_settings.server, defaults)
        self.assertEqual(ogc_settings.rest, defaults['LOCATION'] + 'rest')
        self.assertEqual(ogc_settings.ows, defaults['LOCATION'] + 'ows')

        # Make sure we get None vs a KeyError when the key does not exist
        self.assertIsNone(ogc_settings.SFDSDFDSF)

        # Testing OWS endpoints
        from django.urls import reverse
        from ..ows import _wcs_get_capabilities, _wfs_get_capabilities, _wms_get_capabilities
        wcs = _wcs_get_capabilities()
        logger.debug(wcs)
        self.assertIsNotNone(wcs)

        try:
            wcs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')

        self.assertTrue(wcs.startswith(wcs_url))
        self.assertIn("service=WCS", wcs)
        self.assertIn("request=GetCapabilities", wcs)
        self.assertIn("version=2.0.1", wcs)

        wfs = _wfs_get_capabilities()
        logger.debug(wfs)
        self.assertIsNotNone(wfs)

        try:
            wfs_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wfs.startswith(wfs_url))
        self.assertIn("service=WFS", wfs)
        self.assertIn("request=GetCapabilities", wfs)
        self.assertIn("version=1.1.0", wfs)

        wms = _wms_get_capabilities()
        logger.debug(wms)
        self.assertIsNotNone(wms)

        try:
            wms_url = urljoin(settings.SITEURL, reverse('ows_endpoint'))
        except BaseException:
            wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'ows')
        self.assertTrue(wms.startswith(wms_url))
        self.assertIn("service=WMS", wms)
        self.assertIn("request=GetCapabilities", wms)
        self.assertIn("version=1.3.0", wms)

        # Test OWS Download Links
        from geonode.geoserver.ows import wcs_links, wfs_links, wms_links
        instance = Layer.objects.all()[0]
        bbox = instance.bbox
        srid = instance.srid
        height = 512
        width = 512

        # Default Style (expect exception since we are offline)
        style = None
        with self.assertRaises(GeoNodeException):
            style = get_sld_for(gs_catalog, instance)
        self.assertIsNone(style)
        style = gs_catalog.get_style("line")
        self.assertIsNotNone(style)
        instance.default_style, _ = Style.objects.get_or_create(
            name=style.name,
            defaults=dict(
                sld_title=style.sld_title,
                sld_body=style.sld_body
            )
        )
        self.assertIsNotNone(instance.default_style)
        self.assertIsNotNone(instance.default_style.name)

        # WMS Links
        wms_links = wms_links(ogc_settings.public_url + 'wms?',
                              instance.alternate,
                              bbox,
                              srid,
                              height,
                              width)
        self.assertIsNotNone(wms_links)
        self.assertEquals(len(wms_links), 3)
        wms_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wms')
        identifier = urlencode({'layers': instance.alternate})
        for _link in wms_links:
            logger.debug('%s --> %s' % (wms_url, _link[3]))
            self.assertTrue(wms_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WFS Links
        wfs_links = wfs_links(ogc_settings.public_url + 'wfs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wfs_links)
        self.assertEquals(len(wfs_links), 6)
        wfs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wfs')
        identifier = urlencode({'typename': instance.alternate})
        for _link in wfs_links:
            logger.debug('%s --> %s' % (wfs_url, _link[3]))
            self.assertTrue(wfs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # WCS Links
        wcs_links = wcs_links(ogc_settings.public_url + 'wcs?',
                              instance.alternate,
                              bbox,
                              srid)
        self.assertIsNotNone(wcs_links)
        self.assertEquals(len(wcs_links), 2)
        wcs_url = urljoin(ogc_settings.PUBLIC_LOCATION, 'wcs')
        identifier = urlencode({'coverageid': instance.alternate})
        for _link in wcs_links:
            logger.debug('%s --> %s' % (wcs_url, _link[3]))
            self.assertTrue(wcs_url in _link[3])
            logger.debug('%s --> %s' % (identifier, _link[3]))
            self.assertTrue(identifier in _link[3])

        # Thumbnails Generation Default
        create_gs_thumbnail(instance, overwrite=True)
        self.assertIsNotNone(instance.get_thumbnail_url())

        # Thumbnails Generation Through "remote url"
        create_gs_thumbnail_geonode(instance, overwrite=True, check_bbox=True)

        # Thumbnails Generation Through "image"
        request_body = {
            'width': width,
            'height': height,
            'layers': instance.alternate
        }
        if hasattr(instance, 'default_style'):
            if instance.default_style:
                request_body['styles'] = instance.default_style.name
        self.assertIsNotNone(request_body['styles'])

        try:
            image = _prepare_thumbnail_body_from_opts(request_body)
        except BaseException as e:
            logger.exception(e)
            image = None
        # We are offline here, the layer does not exists in GeoServer
        # - we expect the image is None
        self.assertIsNone(image)
Example #11
0
def construct_wms_url(
    ogc_server_location: str,
    layers: List,
    bbox: List,
    wms_version: str = settings.OGC_SERVER["default"].get(
        "WMS_VERSION", "1.1.0"),
    mime_type: str = "image/png",
    styles: str = None,
    width: int = 240,
    height: int = 200,
) -> str:
    """
    Method constructing a GetMap URL to the OGC server.

    :param ogc_server_location: OGC server URL
    :param layers: layers which should be fetched from the OGC server
    :param bbox: area's bounding box in format: [west, east, south, north, CRS]
    :param wms_version: WMS version of the query
    :param mime_type: mime type of the returned image
    :param styles: styles, which OGC server should use for rendering an image
    :param width: width of the returned image
    :param height: height of the returned image

    :return: GetMap URL
    """
    # create GetMap query parameters
    params = {
        "service": "WMS",
        "version": wms_version,
        "request": "GetMap",
        "layers": ",".join(layers),
        "bbox":
        ",".join([str(bbox[0]),
                  str(bbox[2]),
                  str(bbox[1]),
                  str(bbox[3])]),
        "crs": bbox[-1],
        "width": width,
        "height": height,
        "format": mime_type,
        "transparent": True,
    }

    if styles is not None:
        params["styles"] = styles

    # create GetMap request
    ogc_server_settings = OGC_Servers_Handler(settings.OGC_SERVER)["default"]

    if ogc_server_location is not None:
        thumbnail_url = ogc_server_location
    else:
        thumbnail_url = ogc_server_settings.LOCATION

    wms_endpoint = ""
    if thumbnail_url == ogc_server_settings.LOCATION:
        # add access token to requests to Geoserver (logic based on the previous implementation)
        username = ogc_server_settings.credentials.username
        user = get_user_model().objects.filter(username=username).first()
        if user:
            access_token = get_or_create_token(user)
            if access_token and not access_token.is_expired():
                params["access_token"] = access_token.token

        # add WMS endpoint to requests to Geoserver
        wms_endpoint = getattr(ogc_server_settings, "WMS_ENDPOINT") or "ows"

    thumbnail_url = f"{thumbnail_url}{wms_endpoint}?{'&'.join(f'{key}={val}' for key, val in params.items())}"

    return thumbnail_url