Exemple #1
0
def map_embed(request, mapid=None, template='maps/map_embed.html'):
    try:
        map_obj = _resolve_map(request, mapid, 'base.view_resourcebase',
                               _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(MSG_NOT_ALLOWED, status=403)
    except Exception:
        raise Http404(MSG_NOT_FOUND)

    if not map_obj:
        raise Http404(MSG_NOT_FOUND)

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    context_dict = {
        'access_token': access_token,
        'resource': map_obj,
    }

    register_event(request, EventType.EVENT_VIEW, map_obj)
    return render(request, template, context=context_dict)
Exemple #2
0
def dataset_detail(request,
                   layername,
                   template='datasets/dataset_detail.html'):
    try:
        layer = _resolve_dataset(request, layername, 'base.view_resourcebase',
                                 _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not layer:
        raise Http404(_("Not found"))

    # Update count for popularity ranking,
    # but do not includes admins or resource owners
    layer.view_count_up(request.user)

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    context_dict = {
        'access_token': access_token,
        'resource': layer,
    }
    register_event(request, 'view', layer)
    return TemplateResponse(request, template, context=context_dict)
Exemple #3
0
def geoapp_edit(request, geoappid, template='apps/app_edit.html'):
    """
    The view that returns the app composer opened to
    the app with the given app ID.
    """
    try:
        geoapp_obj = _resolve_geoapp(
            request,
            geoappid,
            'base.view_resourcebase',
            _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not geoapp_obj:
        raise Http404(_("Not found"))

    # Call this first in order to be sure "perms_list" is correct
    permissions_json = _perms_info_json(geoapp_obj)

    perms_list = list(
        geoapp_obj.get_self_resource().get_user_perms(request.user)
        .union(geoapp_obj.get_user_perms(request.user))
    )

    group = None
    if geoapp_obj.group:
        try:
            group = GroupProfile.objects.get(slug=geoapp_obj.group.name)
        except GroupProfile.DoesNotExist:
            group = None

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    _data = GeoAppData.objects.filter(resource__id=geoappid).first()
    _config = _data.blob if _data else {}
    _ctx = {
        'appId': geoappid,
        'appType': geoapp_obj.type,
        'config': _config,
        'user': request.user,
        'access_token': access_token,
        'resource': geoapp_obj,
        'group': group,
        'perms_list': perms_list,
        "permissions_json": permissions_json,
        'preview': getattr(
            settings,
            'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY',
            'mapstore')
    }

    return render(request, template, context=_ctx)
Exemple #4
0
    def test_outh_token(self):
        user = '******'
        _user = get_user_model().objects.get(username=user)
        token = get_or_create_token(_user)
        auth_header = f'Bearer {token}'
        list_url = reverse('api_dispatch_list',
                           kwargs={
                               'api_name': 'api',
                               'resource_name': 'datasets'
                           })

        with self.settings(SESSION_EXPIRED_CONTROL_ENABLED=False,
                           DELAYED_SECURITY_SIGNALS=False):
            # all public
            resp = self.api_client.get(list_url)
            self.assertValidJSONResponse(resp)
            self.assertGreaterEqual(len(self.deserialize(resp)['objects']), 7)

            perm_spec = {
                "users": {
                    "admin": ['view_resourcebase']
                },
                "groups": {}
            }
            layer = Dataset.objects.all()[0]
            layer.set_permissions(perm_spec)
            resp = self.api_client.get(list_url)
            self.assertGreaterEqual(len(self.deserialize(resp)['objects']), 7)

            resp = self.api_client.get(list_url, authentication=auth_header)
            self.assertGreaterEqual(len(self.deserialize(resp)['objects']), 7)

            layer.is_published = False
            layer.save()
Exemple #5
0
 def test_inbox_renders(self):
     logged_in = self.client.login(
         username=self.first_user.username, password=self.user_password)
     self.assertTrue(logged_in)
     session = self.client.session
     session['access_token'] = get_or_create_token(self.first_user)
     session.save()
     response = self.client.get(reverse("messages_inbox"))
     self.assertTemplateUsed(response, "user_messages/inbox.html")
     self.assertEqual(response.status_code, 200)
Exemple #6
0
 def test_inbox_renders(self):
     logged_in = self.client.login(
         username=self.first_user.username, password=self.user_password)
     self.assertTrue(logged_in)
     session = self.client.session
     session['access_token'] = get_or_create_token(self.first_user)
     session.save()
     response = self.client.get(reverse("messages_inbox"))
     self.assertTemplateUsed(response, "user_messages/inbox.html")
     self.assertEqual(response.status_code, 200)
Exemple #7
0
 def setUp(self):
     super(DataTypeResourceTests, self).setUp()
     self.user = get_user_model().objects.get(username="******")
     self.list_url = reverse('api_dispatch_list',
                             kwargs={
                                 'api_name': 'api',
                                 'resource_name': 'datatype'
                             })
     all_public()
     self.token = get_or_create_token(self.user)
     self.auth_header = f'Bearer {self.token}'
Exemple #8
0
 def setUp(self):
     super(LayerResourceTests, self).setUp()
     self.user = get_user_model().objects.get(username="******")
     self.list_url = reverse('api_dispatch_list',
                             kwargs={
                                 'api_name': 'api',
                                 'resource_name': 'layers'
                             })
     all_public()
     self.token = get_or_create_token(self.user)
     self.auth_header = 'Bearer {}'.format(self.token)
Exemple #9
0
    def test_the_api_should_return_all_datasets_with_metadata_false(self):
        list_url = reverse('api_dispatch_list',
                           kwargs={
                               'api_name': 'api',
                               'resource_name': 'datasets'
                           })
        user = get_user_model().objects.get(username="******")
        token = get_or_create_token(user)
        auth_header = f'Bearer {token}'

        resp = self.api_client.get(list_url, authentication=auth_header)
        self.assertValidJSONResponse(resp)
        self.assertEqual(8, resp.json()["meta"]["total_count"])
Exemple #10
0
    def setUp(self):
        super(OAuthApiTests, self).setUp()

        self.user = '******'
        self.passwd = 'admin'
        self._user = get_user_model().objects.get(username=self.user)
        self.token = get_or_create_token(self._user)
        self.auth_header = f'Bearer {self.token}'
        self.list_url = reverse('api_dispatch_list',
                                kwargs={
                                    'api_name': 'api',
                                    'resource_name': 'layers'
                                })
        all_public()
        self.perm_spec = {"users": {}, "groups": {}}
Exemple #11
0
    def setUp(self):
        super(OAuthApiTests, self).setUp()

        self.user = '******'
        self.passwd = 'admin'
        self._user = get_user_model().objects.get(username=self.user)
        self.token = get_or_create_token(self._user)
        self.auth_header = 'Bearer {}'.format(self.token)
        self.list_url = reverse(
            'api_dispatch_list',
            kwargs={
                'api_name': 'api',
                'resource_name': 'layers'})
        all_public()
        self.perm_spec = {"users": {}, "groups": {}}
Exemple #12
0
def profile_detail(request, username):
    profile = get_object_or_404(get_user_model(), Q(is_active=True), username=username)
    # combined queryset from each model content type

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    return render(request, "people/profile_detail.html", {
        'access_token': access_token,
        "profile": profile,
    })
Exemple #13
0
def do_login(sender, user, request, **kwargs):
    """
    Take action on user login. Generate a new user access_token to be shared
    with GeoServer, and store it into the request.session
    """
    if user and user.is_authenticated:
        token = None
        try:
            token = get_or_create_token(user)
        except Exception:
            u = uuid1()
            token = u.hex
            tb = traceback.format_exc()
            logger.debug(tb)

        set_session_token(request.session, token)
Exemple #14
0
def do_login(sender, user, request, **kwargs):
    """
    Take action on user login. Generate a new user access_token to be shared
    with GeoServer, and store it into the request.session
    """
    if user and user.is_authenticated():
        token = None
        try:
            token = get_or_create_token(user)
        except BaseException:
            u = uuid1()
            token = u.hex
            tb = traceback.format_exc()
            logger.debug(tb)

        set_session_token(request.session, token)
Exemple #15
0
def new_geoapp(request, template='apps/app_new.html'):

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    if request.method == 'GET':
        _ctx = {
            'user': request.user,
            'access_token': access_token,
        }
        return render(request, template, context=_ctx)

    return HttpResponseRedirect(hookset.geoapp_list_url())
Exemple #16
0
def _get_topomap_sheets(
        topomap: PublishedTopoMapIndexSheetLayer) -> typing.List:
    geoserver_admin_user = get_user_model().objects.get(
        username=settings.OGC_SERVER_DEFAULT_USER)
    access_token = get_or_create_token(geoserver_admin_user)
    published_sheets = topomap.get_published_sheets(
        use_public_wfs_url=False, geoserver_access_token=access_token)
    sheets_info = []
    for sheet_index in published_sheets:
        sheet_paths = utils.find_sheet(topomap.series, topomap.version,
                                       sheet_index)
        if sheet_paths is not None:
            sheets_info.append({
                'index': sheet_index,
                'paper_sizes': sheet_paths.keys()
            })
    sheets_info = sorted(sheets_info, key=lambda x: x['index'])
    return sheets_info
def do_login(sender, user, request, **kwargs):
    """
    Take action on user login. Generate a new user access_token to be shared
    with GeoServer, and store it into the request.session
    """
    if user and user.is_authenticated:
        token = None
        try:
            token = get_or_create_token(user)
        except Exception:
            u = uuid1()
            token = u.hex
            tb = traceback.format_exc()
            logger.debug(tb)

        set_session_token(request.session, token)

        if groups_settings.AUTO_ASSIGN_REGISTERED_MEMBERS_TO_REGISTERED_MEMBERS_GROUP_AT == 'login':
            _add_user_to_registered_members(user)
Exemple #18
0
def do_login(sender, user, request, **kwargs):
    """
    Take action on user login. Generate a new user access_token to be shared
    with GeoServer, and store it into the request.session
    """
    if user and user.is_authenticated():
        token = None
        try:
            token = get_or_create_token(user)
        except BaseException:
            u = uuid1()
            token = u.hex
            tb = traceback.format_exc()
            logger.debug(tb)

        set_session_token(request.session, token)

        from geonode.groups.conf import settings as groups_settings
        if groups_settings.AUTO_ASSIGN_REGISTERED_MEMBERS_TO_REGISTERED_MEMBERS_GROUP_NAME:
            group_name = groups_settings.REGISTERED_MEMBERS_GROUP_NAME
            groupprofile = GroupProfile.objects.filter(slug=group_name).first()
            if groupprofile and not groupprofile.user_is_member(user):
                groupprofile.join(user)
Exemple #19
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
Exemple #20
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

    if thumbnail_url.startswith(ogc_server_settings.PUBLIC_LOCATION):
        thumbnail_url = thumbnail_url.replace(ogc_server_settings.PUBLIC_LOCATION, 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 thumbnail_url.startswith(ogc_server_settings.LOCATION):
        if "access_token" not in additional_kwargs.keys():
            # for the Geoserver backend, use Basic Auth, if access_token is not provided
            _user, _pwd = ogc_server_settings.credentials
            encoded_credentials = base64.b64encode(f"{_user}:{_pwd}".encode("UTF-8")).decode("ascii")
            headers["Authorization"] = f"Basic {encoded_credentials}"
        else:
            headers["Authorization"] = f"Bearer {additional_kwargs['access_token']}"

    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] if bbox else None,
                bbox=[bbox[0], bbox[2], bbox[1], bbox[3]] if bbox else None,
                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()
Exemple #21
0
def geoapp_detail(request, geoappid, template='apps/app_detail.html'):
    """
    The view that returns the app composer opened to
    the app with the given app ID.
    """
    try:
        geoapp_obj = _resolve_geoapp(request, geoappid,
                                     'base.view_resourcebase',
                                     _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not geoapp_obj:
        raise Http404(_("Not found"))

    # Add metadata_author or poc if missing
    geoapp_obj.add_missing_metadata_author_or_poc()

    # Update count for popularity ranking,
    # but do not includes admins or resource owners
    if request.user != geoapp_obj.owner and not request.user.is_superuser:
        GeoApp.objects.filter(id=geoapp_obj.id).update(
            popular_count=F('popular_count') + 1)

    _data = GeoAppData.objects.filter(resource__id=geoappid).first()
    _config = _data.blob if _data else {}

    # Call this first in order to be sure "perms_list" is correct
    permissions_json = _perms_info_json(geoapp_obj)

    perms_list = get_perms(request.user,
                           geoapp_obj.get_self_resource()) + get_perms(
                               request.user, geoapp_obj)

    group = None
    if geoapp_obj.group:
        try:
            group = GroupProfile.objects.get(slug=geoapp_obj.group.name)
        except GroupProfile.DoesNotExist:
            group = None

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    context_dict = {
        'appId':
        geoappid,
        'appType':
        geoapp_obj.type,
        'config':
        _config,
        'user':
        request.user,
        'access_token':
        access_token,
        'resource':
        geoapp_obj,
        'group':
        group,
        'perms_list':
        perms_list,
        'permissions_json':
        permissions_json,
        'preview':
        getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore'),
        'crs':
        getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857')
    }

    if settings.SOCIAL_ORIGINS:
        context_dict["social_links"] = build_social_links(request, geoapp_obj)

    register_event(request, EventType.EVENT_VIEW, request.path)

    return render(request, template, context=context_dict)
Exemple #22
0
def create_gs_thumbnail_geonode(instance, overwrite=False, check_bbox=False):
    """
    Create a thumbnail with a GeoServer request.
    """
    layers = None
    bbox = None  # x0, x1, y0, y1
    local_layers = []
    local_bboxes = []
    if isinstance(instance, Map):
        # a map could be empty!
        if not instance.layers:
            return
        for layer in instance.layers:
            if layer.local:
                local_layers.append(layer.name)
                # Compute Bounds
                _l = Layer.objects.get(alternate=layer.name)
                wgs84_bbox = bbox_to_projection(_l.bbox)
                local_bboxes.append(wgs84_bbox)
        layers = ",".join(local_layers).encode('utf-8')
    else:
        layers = instance.alternate.encode('utf-8')
        # Compute Bounds
        _l = Layer.objects.get(alternate=layers)
        wgs84_bbox = bbox_to_projection(_l.bbox)
        local_bboxes.append(wgs84_bbox)

    if local_bboxes:
        for _bbox in local_bboxes:
            if bbox is None:
                bbox = list(_bbox)
            else:
                if bbox[0] > _bbox[0]:
                    bbox[0] = _bbox[0]
                if bbox[1] < _bbox[1]:
                    bbox[1] = _bbox[1]
                if bbox[2] > _bbox[2]:
                    bbox[2] = _bbox[2]
                if bbox[3] < _bbox[3]:
                    bbox[3] = _bbox[3]

    wms_endpoint = getattr(ogc_server_settings, 'WMS_ENDPOINT') or 'ows'
    wms_version = getattr(ogc_server_settings, 'WMS_VERSION') or '1.1.1'
    wms_format = getattr(ogc_server_settings, 'WMS_FORMAT') or 'image/png8'

    params = {
        'service': 'WMS',
        'version': wms_version,
        'request': 'GetMap',
        'layers': layers,
        'format': wms_format,
        # 'TIME': '-99999999999-01-01T00:00:00.0Z/99999999999-01-01T00:00:00.0Z'
    }

    if bbox:
        params['bbox'] = "%s,%s,%s,%s" % (bbox[0], bbox[2], bbox[1], bbox[3])
        params['crs'] = 'EPSG:4326'
        params['width'] = 240
        params['height'] = 180

    user = None
    try:
        username = ogc_server_settings.credentials.username
        user = get_user_model().objects.get(username=username)
    except BaseException as e:
        logger.exception(e)

    access_token = None
    if user:
        access_token = get_or_create_token(user)
        if access_token and not access_token.is_expired():
            params['access_token'] = access_token.token

    # Avoid using urllib.urlencode here because it breaks the url.
    # commas and slashes in values get encoded and then cause trouble
    # with the WMS parser.
    _p = "&".join("%s=%s" % item for item in params.items())

    import posixpath
    thumbnail_remote_url = posixpath.join(
        ogc_server_settings.PUBLIC_LOCATION,
        wms_endpoint) + "?" + _p
    thumbnail_create_url = posixpath.join(
        ogc_server_settings.LOCATION,
        wms_endpoint) + "?" + _p

    create_thumbnail(instance, thumbnail_remote_url, thumbnail_create_url,
                     overwrite=overwrite, check_bbox=check_bbox)
Exemple #23
0
def document_detail(request, docid):
    """
    The view that show details of each document
    """
    document = None
    try:
        document = _resolve_document(request, docid, 'base.view_resourcebase',
                                     _PERMISSION_MSG_VIEW)
    except Http404:
        return HttpResponse(loader.render_to_string('404.html',
                                                    context={},
                                                    request=request),
                            status=404)

    except PermissionDenied:
        return HttpResponse(loader.render_to_string(
            '401.html',
            context={
                'error_message':
                _("You are not allowed to view this document.")
            },
            request=request),
                            status=403)

    if document is None:
        return HttpResponse('An unknown error has occured.',
                            content_type="text/plain",
                            status=401)
    else:
        permission_manager = ManageResourceOwnerPermissions(document)
        permission_manager.set_owner_permissions_according_to_workflow()

        # Add metadata_author or poc if missing
        document.add_missing_metadata_author_or_poc()

        related = get_related_resources(document)

        # Update count for popularity ranking,
        # but do not includes admins or resource owners
        if request.user != document.owner and not request.user.is_superuser:
            Document.objects.filter(id=document.id).update(
                popular_count=F('popular_count') + 1)

        metadata = document.link_set.metadata().filter(
            name__in=settings.DOWNLOAD_FORMATS_METADATA)

        # Call this first in order to be sure "perms_list" is correct
        permissions_json = _perms_info_json(document)

        perms_list = get_perms(request.user,
                               document.get_self_resource()) + get_perms(
                                   request.user, document)

        group = None
        if document.group:
            try:
                group = GroupProfile.objects.get(slug=document.group.name)
            except ObjectDoesNotExist:
                group = None

        access_token = None
        if request and request.user:
            access_token = get_or_create_token(request.user)
            if access_token and not access_token.is_expired():
                access_token = access_token.token
            else:
                access_token = None

        context_dict = {
            'access_token': access_token,
            'resource': document,
            'perms_list': perms_list,
            'permissions_json': permissions_json,
            'group': group,
            'metadata': metadata,
            'imgtypes': IMGTYPES,
            'related': related
        }

        if settings.SOCIAL_ORIGINS:
            context_dict["social_links"] = build_social_links(
                request, document)

        if getattr(settings, 'EXIF_ENABLED', False):
            try:
                from geonode.documents.exif.utils import exif_extract_dict
                exif = exif_extract_dict(document)
                if exif:
                    context_dict['exif_data'] = exif
            except Exception:
                logger.error("Exif extraction failed.")

        if request.user.is_authenticated:
            if getattr(settings, 'FAVORITE_ENABLED', False):
                from geonode.favorite.utils import get_favorite_info
                context_dict["favorite_info"] = get_favorite_info(
                    request.user, document)

        register_event(request, EventType.EVENT_VIEW, document)

        return render(request,
                      "documents/document_detail.html",
                      context=context_dict)
Exemple #24
0
def map_detail(request, mapid, template='maps/map_detail.html'):
    '''
    The view that show details of each map
    '''
    map_obj = _resolve_map(request, mapid, 'base.view_resourcebase',
                           _PERMISSION_MSG_VIEW)

    permission_manager = ManageResourceOwnerPermissions(map_obj)
    permission_manager.set_owner_permissions_according_to_workflow()

    # Add metadata_author or poc if missing
    map_obj.add_missing_metadata_author_or_poc()

    # Update count for popularity ranking,
    # but do not includes admins or resource owners
    if request.user != map_obj.owner and not request.user.is_superuser:
        Map.objects.filter(id=map_obj.id).update(
            popular_count=F('popular_count') + 1)

    config = map_obj.viewer_json(request)

    register_event(request, EventType.EVENT_VIEW, map_obj.title)

    config = json.dumps(config)
    layers = MapLayer.objects.filter(map=map_obj.id)
    links = map_obj.link_set.download()

    # Call this first in order to be sure "perms_list" is correct
    permissions_json = _perms_info_json(map_obj)

    perms_list = get_perms(request.user,
                           map_obj.get_self_resource()) + get_perms(
                               request.user, map_obj)

    group = None
    if map_obj.group:
        try:
            group = GroupProfile.objects.get(slug=map_obj.group.name)
        except GroupProfile.DoesNotExist:
            group = None

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    context_dict = {
        'access_token':
        access_token,
        'config':
        config,
        'resource':
        map_obj,
        'group':
        group,
        'layers':
        layers,
        'perms_list':
        perms_list,
        'permissions_json':
        permissions_json,
        "documents":
        get_related_documents(map_obj),
        'links':
        links,
        'preview':
        getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore'),
        'crs':
        getattr(settings, 'DEFAULT_MAP_CRS', 'EPSG:3857')
    }

    if settings.SOCIAL_ORIGINS:
        context_dict["social_links"] = build_social_links(request, map_obj)

    if request.user.is_authenticated:
        if getattr(settings, 'FAVORITE_ENABLED', False):
            from geonode.favorite.utils import get_favorite_info
            context_dict["favorite_info"] = get_favorite_info(
                request.user, map_obj)

    register_event(request, EventType.EVENT_VIEW, request.path)

    return render(request, template, context=context_dict)
Exemple #25
0
def csw_global_dispatch(request, layer_filter=None, config_updater=None):
    """pycsw wrapper"""

    # this view should only operate if pycsw_local is the backend
    # else, redirect to the URL of the non-pycsw_local backend
    if settings.CATALOGUE['default'][
            'ENGINE'] != 'geonode.catalogue.backends.pycsw_local':
        return HttpResponseRedirect(settings.CATALOGUE['default']['URL'])

    mdict = dict(settings.PYCSW['CONFIGURATION'], **CONFIGURATION)
    mdict = config_updater(mdict) if config_updater else mdict

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and access_token.is_expired():
            access_token = None

    absolute_uri = f'{request.build_absolute_uri()}'
    query_string = f"{request.META['QUERY_STRING']}"
    env = request.META.copy()

    if access_token and not access_token.is_expired():
        env.update({'access_token': access_token.token})
        if 'access_token' not in query_string:
            absolute_uri = f'{absolute_uri}&access_token={access_token.token}'
            query_string = f'{query_string}&access_token={access_token.token}'

    env.update({
        'local.app_root': os.path.dirname(__file__),
        'REQUEST_URI': absolute_uri,
        'QUERY_STRING': query_string
    })

    # Save original filter before doing anything
    mdict_filter = mdict['repository']['filter']

    try:
        # Filter out Layers not accessible to the User
        authorized_ids = []
        if request.user:
            profiles = get_user_model().objects.filter(
                username=str(request.user))
        else:
            profiles = get_user_model().objects.filter(
                username="******")
        if profiles:
            authorized = list(
                get_objects_for_user(profiles[0],
                                     'base.view_resourcebase').values('id'))

            layers = ResourceBase.objects.filter(
                id__in=[d['id'] for d in authorized])

            if layer_filter and layers:
                layers = layer_filter(layers)

            if layers:
                authorized_ids = [d.id for d in layers]

        if len(authorized_ids) > 0:
            authorized_layers = "(" + (", ".join(
                str(e) for e in authorized_ids)) + ")"
            authorized_layers_filter = "id IN " + authorized_layers
            mdict['repository']['filter'] += " AND " + authorized_layers_filter
            if request.user and request.user.is_authenticated:
                mdict['repository'][
                    'filter'] = f"({mdict['repository']['filter']}) OR ({authorized_layers_filter})"
        else:
            authorized_layers_filter = "id = -9999"
            mdict['repository']['filter'] += " AND " + authorized_layers_filter

        # Filter out Documents and Maps
        if 'ALTERNATES_ONLY' in settings.CATALOGUE[
                'default'] and settings.CATALOGUE['default']['ALTERNATES_ONLY']:
            mdict['repository']['filter'] += " AND alternate IS NOT NULL"

        # Filter out Layers belonging to specific Groups
        is_admin = False
        if request.user:
            is_admin = request.user.is_superuser if request.user else False

        if not is_admin and settings.GROUP_PRIVATE_RESOURCES:
            groups_ids = []
            if request.user and request.user.is_authenticated:
                for group in request.user.groups.all():
                    groups_ids.append(group.id)
                group_list_all = []
                try:
                    group_list_all = request.user.group_list_all().values(
                        'group')
                except Exception:
                    pass
                for group in group_list_all:
                    if isinstance(group, dict):
                        if 'group' in group:
                            groups_ids.append(group['group'])
                    else:
                        groups_ids.append(group.id)

            public_groups = GroupProfile.objects.exclude(
                access="private").values('group')
            for group in public_groups:
                if isinstance(group, dict):
                    if 'group' in group:
                        groups_ids.append(group['group'])
                else:
                    groups_ids.append(group.id)

            if len(groups_ids) > 0:
                groups = "(" + (", ".join(str(e) for e in groups_ids)) + ")"
                groups_filter = "(group_id IS NULL OR group_id IN " + groups + ")"
                mdict['repository']['filter'] += " AND " + groups_filter
            else:
                groups_filter = "group_id IS NULL"
                mdict['repository']['filter'] += " AND " + groups_filter

        csw = server.Csw(mdict, env, version='2.0.2')

        content = csw.dispatch_wsgi()

        # pycsw 2.0 has an API break:
        # - pycsw < 2.0: content = xml_response
        # - pycsw >= 2.0: content = [http_status_code, content]
        # deal with the API break

        if isinstance(content, list):  # pycsw 2.0+
            content = content[1]

    finally:
        # Restore original filter before doing anything
        mdict['repository']['filter'] = mdict_filter

    return HttpResponse(content, content_type=csw.contenttype)
Exemple #26
0
def document_detail(request, docid):
    """
    The view that show details of each document
    """
    try:
        document = _resolve_document(request, docid, 'base.view_resourcebase',
                                     _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not document:
        raise Http404(_("Not found"))

    permission_manager = ManageResourceOwnerPermissions(document)
    permission_manager.set_owner_permissions_according_to_workflow()

    # Add metadata_author or poc if missing
    document.add_missing_metadata_author_or_poc()

    related = get_related_resources(document)

    # Update count for popularity ranking,
    # but do not includes admins or resource owners
    if request.user != document.owner and not request.user.is_superuser:
        Document.objects.filter(id=document.id).update(
            popular_count=F('popular_count') + 1)

    metadata = document.link_set.metadata().filter(
        name__in=settings.DOWNLOAD_FORMATS_METADATA)

    # Call this first in order to be sure "perms_list" is correct
    permissions_json = _perms_info_json(document)

    perms_list = list(document.get_self_resource().get_user_perms(
        request.user).union(document.get_user_perms(request.user)))

    group = None
    if document.group:
        try:
            group = GroupProfile.objects.get(slug=document.group.name)
        except ObjectDoesNotExist:
            group = None

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    AUDIOTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'audio']
    IMGTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'image']
    VIDEOTYPES = [_e for _e, _t in DOCUMENT_TYPE_MAP.items() if _t == 'video']

    context_dict = {
        'access_token': access_token,
        'resource': document,
        'perms_list': perms_list,
        'permissions_json': permissions_json,
        'group': group,
        'metadata': metadata,
        'audiotypes': AUDIOTYPES,
        'imgtypes': IMGTYPES,
        'videotypes': VIDEOTYPES,
        'mimetypemap': DOCUMENT_MIMETYPE_MAP,
        'related': related
    }

    if settings.SOCIAL_ORIGINS:
        context_dict["social_links"] = build_social_links(request, document)

    if getattr(settings, 'EXIF_ENABLED', False):
        try:
            from geonode.documents.exif.utils import exif_extract_dict
            exif = exif_extract_dict(document)
            if exif:
                context_dict['exif_data'] = exif
        except Exception:
            logger.debug("Exif extraction failed.")

    if request.user.is_authenticated:
        if getattr(settings, 'FAVORITE_ENABLED', False):
            from geonode.favorite.utils import get_favorite_info
            context_dict["favorite_info"] = get_favorite_info(
                request.user, document)

    register_event(request, EventType.EVENT_VIEW, document)

    return render(request,
                  "documents/document_detail.html",
                  context=context_dict)
Exemple #27
0
def geoapp_edit(request, geoappid, template='apps/app_edit.html'):
    """
    The view that returns the app composer opened to
    the app with the given app ID.
    """
    try:
        geoapp_obj = _resolve_geoapp(request, geoappid,
                                     'base.view_resourcebase',
                                     _PERMISSION_MSG_VIEW)
    except PermissionDenied:
        return HttpResponse(_("Not allowed"), status=403)
    except Exception:
        raise Http404(_("Not found"))
    if not geoapp_obj:
        raise Http404(_("Not found"))

    # Call this first in order to be sure "perms_list" is correct
    permissions_json = _perms_info_json(geoapp_obj)

    perms_list = list(geoapp_obj.get_self_resource().get_user_perms(
        request.user).union(geoapp_obj.get_user_perms(request.user)))

    group = None
    if geoapp_obj.group:
        try:
            group = GroupProfile.objects.get(slug=geoapp_obj.group.name)
        except GroupProfile.DoesNotExist:
            group = None

    r = geoapp_obj
    if request.method in ('POST', 'PATCH', 'PUT'):
        r = resource_manager.update(geoapp_obj.uuid,
                                    instance=geoapp_obj,
                                    notify=True)

        resource_manager.set_permissions(
            geoapp_obj.uuid,
            instance=geoapp_obj,
            permissions=ast.literal_eval(permissions_json))

        resource_manager.set_thumbnail(geoapp_obj.uuid,
                                       instance=geoapp_obj,
                                       overwrite=False)

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and not access_token.is_expired():
            access_token = access_token.token
        else:
            access_token = None

    _config = json.dumps(r.blob)
    _ctx = {
        'appId':
        geoappid,
        'appType':
        geoapp_obj.resource_type,
        'config':
        _config,
        'user':
        request.user,
        'access_token':
        access_token,
        'resource':
        geoapp_obj,
        'group':
        group,
        'perms_list':
        perms_list,
        "permissions_json":
        permissions_json,
        'preview':
        getattr(settings, 'GEONODE_CLIENT_LAYER_PREVIEW_LIBRARY', 'mapstore')
    }

    return render(request, template, context=_ctx)
Exemple #28
0
def csw_global_dispatch(request):
    """pycsw wrapper"""

    # this view should only operate if pycsw_local is the backend
    # else, redirect to the URL of the non-pycsw_local backend
    if settings.CATALOGUE['default']['ENGINE'] != 'geonode.catalogue.backends.pycsw_local':
        return HttpResponseRedirect(settings.CATALOGUE['default']['URL'])

    mdict = dict(settings.PYCSW['CONFIGURATION'], **CONFIGURATION)

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and access_token.is_expired():
            access_token = None

    absolute_uri = ('%s' % request.build_absolute_uri())
    query_string = ('%s' % request.META['QUERY_STRING'])
    env = request.META.copy()

    if access_token and not access_token.is_expired():
        env.update({'access_token': access_token.token})
        if 'access_token' not in query_string:
            absolute_uri = ('%s&access_token=%s' % (absolute_uri, access_token.token))
            query_string = ('%s&access_token=%s' % (query_string, access_token.token))

    env.update({'local.app_root': os.path.dirname(__file__),
                'REQUEST_URI': absolute_uri,
                'QUERY_STRING': query_string})

    # Save original filter before doing anything
    mdict_filter = mdict['repository']['filter']

    try:
        # Filter out Layers not accessible to the User
        authorized_ids = []
        if request.user:
            profiles = Profile.objects.filter(username=str(request.user))
        else:
            profiles = Profile.objects.filter(username="******")
        if profiles:
            authorized = list(
                get_objects_for_user(
                    profiles[0],
                    'base.view_resourcebase').values('id'))
            layers = ResourceBase.objects.filter(
                id__in=[d['id'] for d in authorized])
            if layers:
                authorized_ids = [d['id'] for d in authorized]

        if len(authorized_ids) > 0:
            authorized_layers = "(" + (", ".join(str(e)
                                                 for e in authorized_ids)) + ")"
            authorized_layers_filter = "id IN " + authorized_layers
            mdict['repository']['filter'] += " AND " + authorized_layers_filter
            if request.user and request.user.is_authenticated():
                mdict['repository']['filter'] = "({}) OR ({})".format(mdict['repository']['filter'],
                                                                      authorized_layers_filter)
        else:
            authorized_layers_filter = "id = -9999"
            mdict['repository']['filter'] += " AND " + authorized_layers_filter

        # Filter out Documents and Maps
        if 'ALTERNATES_ONLY' in settings.CATALOGUE['default'] and settings.CATALOGUE['default']['ALTERNATES_ONLY']:
            mdict['repository']['filter'] += " AND alternate IS NOT NULL"

        # Filter out Layers belonging to specific Groups
        is_admin = False
        if request.user:
            is_admin = request.user.is_superuser if request.user else False

        if not is_admin and settings.GROUP_PRIVATE_RESOURCES:
            groups_ids = []
            if request.user and request.user.is_authenticated():
                for group in request.user.groups.all():
                    groups_ids.append(group.id)
                group_list_all = []
                try:
                    group_list_all = request.user.group_list_all().values('group')
                except BaseException:
                    pass
                for group in group_list_all:
                    if isinstance(group, dict):
                        if 'group' in group:
                            groups_ids.append(group['group'])
                    else:
                        groups_ids.append(group.id)

            public_groups = GroupProfile.objects.exclude(
                access="private").values('group')
            for group in public_groups:
                if isinstance(group, dict):
                    if 'group' in group:
                        groups_ids.append(group['group'])
                else:
                    groups_ids.append(group.id)

            if len(groups_ids) > 0:
                groups = "(" + (", ".join(str(e) for e in groups_ids)) + ")"
                groups_filter = "(group_id IS NULL OR group_id IN " + groups + ")"
                mdict['repository']['filter'] += " AND " + groups_filter
            else:
                groups_filter = "group_id IS NULL"
                mdict['repository']['filter'] += " AND " + groups_filter

        csw = server.Csw(mdict, env, version='2.0.2')

        content = csw.dispatch_wsgi()

        # pycsw 2.0 has an API break:
        # pycsw < 2.0: content = xml_response
        # pycsw >= 2.0: content = [http_status_code, content]
        # deal with the API break

        if isinstance(content, list):  # pycsw 2.0+
            content = content[1]

        spaces = {'csw': 'http://www.opengis.net/cat/csw/2.0.2',
                  'dc': 'http://purl.org/dc/elements/1.1/',
                  'dct': 'http://purl.org/dc/terms/',
                  'gmd': 'http://www.isotc211.org/2005/gmd',
                  'gml': 'http://www.opengis.net/gml',
                  'ows': 'http://www.opengis.net/ows',
                  'xs': 'http://www.w3.org/2001/XMLSchema',
                  'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
                  'ogc': 'http://www.opengis.net/ogc',
                  'gco': 'http://www.isotc211.org/2005/gco',
                  'gmi': 'http://www.isotc211.org/2005/gmi'}

        for prefix, uri in spaces.iteritems():
            ET.register_namespace(prefix, uri)

        if access_token and not access_token.is_expired():
            tree = ET.fromstring(content)
            for online_resource in tree.findall(
                    '*//gmd:CI_OnlineResource', spaces):
                try:
                    linkage = online_resource.find('gmd:linkage', spaces)
                    for url in linkage.findall('gmd:URL', spaces):
                        if url.text:
                            if '?' not in url.text:
                                url.text += "?"
                            else:
                                url.text += "&"
                            url.text += ("access_token=%s" % (access_token.token))
                            url.set('updated', 'yes')
                except BaseException:
                    pass
            content = ET.tostring(tree, encoding='utf8', method='xml')
    finally:
        # Restore original filter before doing anything
        mdict['repository']['filter'] = mdict_filter

    return HttpResponse(content, content_type=csw.contenttype)
Exemple #29
0
def get_headers(request, url, raw_url, allowed_hosts=[]):
    headers = {}
    cookies = None
    csrftoken = None

    if settings.SESSION_COOKIE_NAME in request.COOKIES and is_safe_url(
            url=raw_url, host=url.hostname):
        cookies = request.META["HTTP_COOKIE"]

    for cook in request.COOKIES:
        name = str(cook)
        value = request.COOKIES.get(name)
        if name == 'csrftoken':
            csrftoken = value
        cook = "%s=%s" % (name, value)
        cookies = cook if not cookies else (cookies + '; ' + cook)

    csrftoken = get_token(request) if not csrftoken else csrftoken

    if csrftoken:
        headers['X-Requested-With'] = "XMLHttpRequest"
        headers['X-CSRFToken'] = csrftoken
        cook = "%s=%s" % ('csrftoken', csrftoken)
        cookies = cook if not cookies else (cookies + '; ' + cook)

    if cookies:
        if 'JSESSIONID' in request.session and request.session['JSESSIONID']:
            cookies = cookies + '; JSESSIONID=' + \
                request.session['JSESSIONID']
        headers['Cookie'] = cookies

    if request.method in ("POST", "PUT") and "CONTENT_TYPE" in request.META:
        headers["Content-Type"] = request.META["CONTENT_TYPE"]

    access_token = None
    site_url = urlsplit(settings.SITEURL)
    allowed_hosts += [url.hostname]
    # We want to convert HTTP_AUTH into a Beraer Token only when hitting the local GeoServer
    if site_url.hostname in allowed_hosts:
        # we give precedence to obtained from Aithorization headers
        if 'HTTP_AUTHORIZATION' in request.META:
            auth_header = request.META.get(
                'HTTP_AUTHORIZATION', request.META.get('HTTP_AUTHORIZATION2'))
            if auth_header:
                headers['Authorization'] = auth_header
                access_token = get_token_from_auth_header(
                    auth_header, create_if_not_exists=True)
        # otherwise we check if a session is active
        elif request and request.user.is_authenticated:
            access_token = get_token_object_from_session(request.session)

            # we extend the token in case the session is active but the token expired
            if access_token and access_token.is_expired():
                extend_token(access_token)
            else:
                access_token = get_or_create_token(request.user)

    if access_token:
        headers['Authorization'] = 'Bearer %s' % access_token

    pragma = "no-cache"
    referer = request.META[
        "HTTP_REFERER"] if "HTTP_REFERER" in request.META else \
        "{scheme}://{netloc}/".format(scheme=site_url.scheme,
                                      netloc=site_url.netloc)
    encoding = request.META[
        "HTTP_ACCEPT_ENCODING"] if "HTTP_ACCEPT_ENCODING" in request.META else "gzip"
    headers.update({
        "Pragma": pragma,
        "Referer": referer,
        "Accept-encoding": encoding,
    })

    return (headers, access_token)
Exemple #30
0
def get_capabilities(request, layerid=None, user=None,
                     mapid=None, category=None, tolerant=False):
    """
    Compile a GetCapabilities document containing public layers
    filtered by layer, user, map, or category
    """

    rootdoc = None
    layers = None
    cap_name = ' Capabilities - '
    if layerid is not None:
        layer_obj = Layer.objects.get(id=layerid)
        cap_name += layer_obj.title
        layers = Layer.objects.filter(id=layerid)
    elif user is not None:
        layers = Layer.objects.filter(owner__username=user)
        cap_name += user
    elif category is not None:
        layers = Layer.objects.filter(category__identifier=category)
        cap_name += category
    elif mapid is not None:
        map_obj = Map.objects.get(id=mapid)
        cap_name += map_obj.title
        alternates = []
        for layer in map_obj.layers:
            if layer.local:
                alternates.append(layer.name)
        layers = Layer.objects.filter(alternate__in=alternates)

    for layer in layers:
        if request.user.has_perm('view_resourcebase',
                                 layer.get_self_resource()):
            access_token = get_or_create_token(request.user)
            if access_token and not access_token.is_expired():
                access_token = access_token.token
            else:
                access_token = None
            try:
                workspace, layername = layer.alternate.split(":") if ":" in layer.alternate else (None, layer.alternate)
                layercap = get_layer_capabilities(layer,
                                                  access_token=access_token,
                                                  tolerant=tolerant)
                if layercap:  # 1st one, seed with real GetCapabilities doc
                    try:
                        namespaces = {'wms': 'http://www.opengis.net/wms',
                                      'xlink': 'http://www.w3.org/1999/xlink',
                                      'xsi': 'http://www.w3.org/2001/XMLSchema-instance'}
                        layercap = etree.fromstring(layercap)
                        rootdoc = etree.ElementTree(layercap)
                        format_online_resource(workspace, layername, rootdoc, namespaces)
                        service_name = rootdoc.find('.//wms:Service/wms:Name', namespaces)
                        if service_name:
                            service_name.text = cap_name
                        rootdoc = rootdoc.find('.//wms:Capability/wms:Layer/wms:Layer', namespaces)
                    except Exception as e:
                        import traceback
                        traceback.print_exc()
                        logger.error(
                            "Error occurred creating GetCapabilities for %s: %s" %
                            (layer.typename, str(e)))
                        rootdoc = None
                if not layercap or not rootdoc:
                    # Get the required info from layer model
                    # TODO: store time dimension on DB also
                    tpl = get_template("geoserver/layer.xml")
                    ctx = {
                        'layer': layer,
                        'geoserver_public_url': ogc_server_settings.public_url,
                        'catalogue_url': settings.CATALOGUE['default']['URL'],
                    }
                    gc_str = tpl.render(ctx)
                    gc_str = gc_str.encode("utf-8", "replace")
                    layerelem = etree.XML(gc_str)
                    rootdoc = etree.ElementTree(layerelem)
            except Exception as e:
                import traceback
                traceback.print_exc()
                logger.error(
                    "Error occurred creating GetCapabilities for %s:%s" %
                    (layer.typename, str(e)))
                rootdoc = None
    if rootdoc is not None:
        capabilities = etree.tostring(
            rootdoc,
            xml_declaration=True,
            encoding='UTF-8',
            pretty_print=True)
        return HttpResponse(capabilities, content_type="text/xml")
    return HttpResponse(status=200)
Exemple #31
0
def csw_global_dispatch(request):
    """pycsw wrapper"""

    # this view should only operate if pycsw_local is the backend
    # else, redirect to the URL of the non-pycsw_local backend
    if settings.CATALOGUE['default']['ENGINE'] != 'geonode.catalogue.backends.pycsw_local':
        return HttpResponseRedirect(settings.CATALOGUE['default']['URL'])

    mdict = dict(settings.PYCSW['CONFIGURATION'], **CONFIGURATION)

    access_token = None
    if request and request.user:
        access_token = get_or_create_token(request.user)
        if access_token and access_token.is_expired():
            access_token = None

    absolute_uri = ('%s' % request.build_absolute_uri())
    query_string = ('%s' % request.META['QUERY_STRING'])
    env = request.META.copy()

    if access_token and not access_token.is_expired():
        env.update({'access_token': access_token.token})
        if 'access_token' not in query_string:
            absolute_uri = ('%s&access_token=%s' % (absolute_uri, access_token.token))
            query_string = ('%s&access_token=%s' % (query_string, access_token.token))

    env.update({'local.app_root': os.path.dirname(__file__),
                'REQUEST_URI': absolute_uri,
                'QUERY_STRING': query_string})

    # Save original filter before doing anything
    mdict_filter = mdict['repository']['filter']

    try:
        # Filter out Layers not accessible to the User
        authorized_ids = []
        if request.user:
            profiles = Profile.objects.filter(username=str(request.user))
        else:
            profiles = Profile.objects.filter(username="******")
        if profiles:
            authorized = list(
                get_objects_for_user(
                    profiles[0],
                    'base.view_resourcebase').values('id'))
            layers = ResourceBase.objects.filter(
                id__in=[d['id'] for d in authorized])
            if layers:
                authorized_ids = [d['id'] for d in authorized]

        if len(authorized_ids) > 0:
            authorized_layers = "(" + (", ".join(str(e)
                                                 for e in authorized_ids)) + ")"
            authorized_layers_filter = "id IN " + authorized_layers
            mdict['repository']['filter'] += " AND " + authorized_layers_filter
            if request.user and request.user.is_authenticated:
                mdict['repository']['filter'] = "({}) OR ({})".format(mdict['repository']['filter'],
                                                                      authorized_layers_filter)
        else:
            authorized_layers_filter = "id = -9999"
            mdict['repository']['filter'] += " AND " + authorized_layers_filter

        # Filter out Documents and Maps
        if 'ALTERNATES_ONLY' in settings.CATALOGUE['default'] and settings.CATALOGUE['default']['ALTERNATES_ONLY']:
            mdict['repository']['filter'] += " AND alternate IS NOT NULL"

        # Filter out Layers belonging to specific Groups
        is_admin = False
        if request.user:
            is_admin = request.user.is_superuser if request.user else False

        if not is_admin and settings.GROUP_PRIVATE_RESOURCES:
            groups_ids = []
            if request.user and request.user.is_authenticated:
                for group in request.user.groups.all():
                    groups_ids.append(group.id)
                group_list_all = []
                try:
                    group_list_all = request.user.group_list_all().values('group')
                except BaseException:
                    pass
                for group in group_list_all:
                    if isinstance(group, dict):
                        if 'group' in group:
                            groups_ids.append(group['group'])
                    else:
                        groups_ids.append(group.id)

            public_groups = GroupProfile.objects.exclude(
                access="private").values('group')
            for group in public_groups:
                if isinstance(group, dict):
                    if 'group' in group:
                        groups_ids.append(group['group'])
                else:
                    groups_ids.append(group.id)

            if len(groups_ids) > 0:
                groups = "(" + (", ".join(str(e) for e in groups_ids)) + ")"
                groups_filter = "(group_id IS NULL OR group_id IN " + groups + ")"
                mdict['repository']['filter'] += " AND " + groups_filter
            else:
                groups_filter = "group_id IS NULL"
                mdict['repository']['filter'] += " AND " + groups_filter

        csw = server.Csw(mdict, env, version='2.0.2')

        content = csw.dispatch_wsgi()

        # pycsw 2.0 has an API break:
        # pycsw < 2.0: content = xml_response
        # pycsw >= 2.0: content = [http_status_code, content]
        # deal with the API break

        if isinstance(content, list):  # pycsw 2.0+
            content = content[1]

        spaces = {'csw': 'http://www.opengis.net/cat/csw/2.0.2',
                  'dc': 'http://purl.org/dc/elements/1.1/',
                  'dct': 'http://purl.org/dc/terms/',
                  'gmd': 'http://www.isotc211.org/2005/gmd',
                  'gml': 'http://www.opengis.net/gml',
                  'ows': 'http://www.opengis.net/ows',
                  'xs': 'http://www.w3.org/2001/XMLSchema',
                  'xsi': 'http://www.w3.org/2001/XMLSchema-instance',
                  'ogc': 'http://www.opengis.net/ogc',
                  'gco': 'http://www.isotc211.org/2005/gco',
                  'gmi': 'http://www.isotc211.org/2005/gmi'}

        for prefix, uri in spaces.items():
            ET.register_namespace(prefix, uri)

        if access_token and not access_token.is_expired():
            tree = dlxml.fromstring(content)
            for online_resource in tree.findall(
                    '*//gmd:CI_OnlineResource', spaces):
                try:
                    linkage = online_resource.find('gmd:linkage', spaces)
                    for url in linkage.findall('gmd:URL', spaces):
                        if url.text:
                            if '?' not in url.text:
                                url.text += "?"
                            else:
                                url.text += "&"
                            url.text += ("access_token=%s" % (access_token.token))
                            url.set('updated', 'yes')
                except BaseException:
                    pass
            content = ET.tostring(tree, encoding='utf8', method='xml')
    finally:
        # Restore original filter before doing anything
        mdict['repository']['filter'] = mdict_filter

    return HttpResponse(content, content_type=csw.contenttype)
Exemple #32
0
def create_gs_thumbnail_geonode(instance, overwrite=False, check_bbox=False):
    """
    Create a thumbnail with a GeoServer request.
    """
    layers = None
    bbox = None  # x0, x1, y0, y1
    local_layers = []
    local_bboxes = []
    if isinstance(instance, Map):
        # a map could be empty!
        if not instance.layers:
            return
        for layer in instance.layers:
            if layer.local:
                local_layers.append(layer.name)
                # Compute Bounds
                _l = Layer.objects.get(alternate=layer.name)
                wgs84_bbox = bbox_to_projection(_l.bbox)
                local_bboxes.append(wgs84_bbox)
        layers = ",".join(local_layers).encode('utf-8')
    else:
        layers = instance.alternate.encode('utf-8')
        # Compute Bounds
        _l = Layer.objects.get(alternate=layers)
        wgs84_bbox = bbox_to_projection(_l.bbox)
        local_bboxes.append(wgs84_bbox)

    if local_bboxes:
        for _bbox in local_bboxes:
            if bbox is None:
                bbox = list(_bbox)
            else:
                if bbox[0] > _bbox[0]:
                    bbox[0] = _bbox[0]
                if bbox[1] < _bbox[1]:
                    bbox[1] = _bbox[1]
                if bbox[2] > _bbox[2]:
                    bbox[2] = _bbox[2]
                if bbox[3] < _bbox[3]:
                    bbox[3] = _bbox[3]

    wms_endpoint = getattr(ogc_server_settings, 'WMS_ENDPOINT') or 'ows'
    wms_version = getattr(ogc_server_settings, 'WMS_VERSION') or '1.1.1'
    wms_format = getattr(ogc_server_settings, 'WMS_FORMAT') or 'image/png8'

    params = {
        'service': 'WMS',
        'version': wms_version,
        'request': 'GetMap',
        'layers': layers,
        'format': wms_format,
        # 'TIME': '-99999999999-01-01T00:00:00.0Z/99999999999-01-01T00:00:00.0Z'
    }

    if bbox:
        params['bbox'] = "%s,%s,%s,%s" % (bbox[0], bbox[2], bbox[1], bbox[3])
        params['crs'] = 'EPSG:4326'
        params['width'] = 240
        params['height'] = 180

    user = None
    try:
        username = ogc_server_settings.credentials.username
        user = get_user_model().objects.get(username=username)
    except BaseException as e:
        logger.exception(e)

    access_token = None
    if user:
        access_token = get_or_create_token(user)
        if access_token and not access_token.is_expired():
            params['access_token'] = access_token.token

    # Avoid using urllib.urlencode here because it breaks the url.
    # commas and slashes in values get encoded and then cause trouble
    # with the WMS parser.
    _p = "&".join("%s=%s" % item for item in params.items())

    import posixpath
    thumbnail_remote_url = posixpath.join(ogc_server_settings.PUBLIC_LOCATION,
                                          wms_endpoint) + "?" + _p
    thumbnail_create_url = posixpath.join(ogc_server_settings.LOCATION,
                                          wms_endpoint) + "?" + _p

    create_thumbnail(instance,
                     thumbnail_remote_url,
                     thumbnail_create_url,
                     overwrite=overwrite,
                     check_bbox=check_bbox)
Exemple #33
0
def get_capabilities(request,
                     layerid=None,
                     user=None,
                     mapid=None,
                     category=None,
                     tolerant=False):
    """
    Compile a GetCapabilities document containing public layers
    filtered by layer, user, map, or category
    """

    rootdoc = None
    layers = None
    cap_name = ' Capabilities - '
    if layerid is not None:
        layer_obj = Layer.objects.get(id=layerid)
        cap_name += layer_obj.title
        layers = Layer.objects.filter(id=layerid)
    elif user is not None:
        layers = Layer.objects.filter(owner__username=user)
        cap_name += user
    elif category is not None:
        layers = Layer.objects.filter(category__identifier=category)
        cap_name += category
    elif mapid is not None:
        map_obj = Map.objects.get(id=mapid)
        cap_name += map_obj.title
        alternates = []
        for layer in map_obj.layers:
            if layer.local:
                alternates.append(layer.name)
        layers = Layer.objects.filter(alternate__in=alternates)

    for layer in layers:
        if request.user.has_perm('view_resourcebase',
                                 layer.get_self_resource()):
            access_token = get_or_create_token(request.user)
            if access_token and not access_token.is_expired():
                access_token = access_token.token
            else:
                access_token = None
            try:
                workspace, layername = layer.alternate.split(
                    ":") if ":" in layer.alternate else (None, layer.alternate)
                layercap = get_layer_capabilities(layer,
                                                  access_token=access_token,
                                                  tolerant=tolerant)
                if layercap:  # 1st one, seed with real GetCapabilities doc
                    try:
                        namespaces = {
                            'wms': 'http://www.opengis.net/wms',
                            'xlink': 'http://www.w3.org/1999/xlink',
                            'xsi': 'http://www.w3.org/2001/XMLSchema-instance'
                        }
                        layercap = dlxml.fromstring(layercap)
                        rootdoc = etree.ElementTree(layercap)
                        format_online_resource(workspace, layername, rootdoc,
                                               namespaces)
                        service_name = rootdoc.find('.//wms:Service/wms:Name',
                                                    namespaces)
                        if service_name:
                            service_name.text = cap_name
                        rootdoc = rootdoc.find(
                            './/wms:Capability/wms:Layer/wms:Layer',
                            namespaces)
                    except Exception as e:
                        import traceback
                        traceback.print_exc()
                        logger.error(
                            "Error occurred creating GetCapabilities for %s: %s"
                            % (layer.typename, str(e)))
                        rootdoc = None
                if not layercap or not rootdoc:
                    # Get the required info from layer model
                    # TODO: store time dimension on DB also
                    tpl = get_template("geoserver/layer.xml")
                    ctx = {
                        'layer': layer,
                        'geoserver_public_url': ogc_server_settings.public_url,
                        'catalogue_url': settings.CATALOGUE['default']['URL'],
                    }
                    gc_str = tpl.render(ctx)
                    gc_str = gc_str.encode("utf-8", "replace")
                    layerelem = etree.XML(gc_str)
                    rootdoc = etree.ElementTree(layerelem)
            except Exception as e:
                import traceback
                traceback.print_exc()
                logger.error(
                    "Error occurred creating GetCapabilities for %s:%s" %
                    (layer.typename, str(e)))
                rootdoc = None
    if rootdoc is not None:
        capabilities = etree.tostring(rootdoc,
                                      xml_declaration=True,
                                      encoding='UTF-8',
                                      pretty_print=True)
        return HttpResponse(capabilities, content_type="text/xml")
    return HttpResponse(status=200)
Exemple #34
0
def dataset_download(request, layername):
    try:
        dataset = _resolve_dataset(
            request,
            layername,
            'base.download_resourcebase',
            _PERMISSION_MSG_GENERIC)
    except Exception as e:
        raise Http404(Exception(_("Not found"), e))

    if not settings.USE_GEOSERVER:
        # if GeoServer is not used, we redirect to the proxy download
        return HttpResponseRedirect(reverse('download', args=[dataset.id]))

    download_format = request.GET.get('export_format')

    if download_format and not wps_format_is_supported(download_format, dataset.subtype):
        logger.error("The format provided is not valid for the selected resource")
        return JsonResponse({"error": "The format provided is not valid for the selected resource"}, status=500)

    _format = 'application/zip' if dataset.is_vector() else 'image/tiff'
    # getting default payload
    tpl = get_template("geoserver/dataset_download.xml")
    ctx = {
        "alternate": dataset.alternate,
        "download_format": download_format or _format
    }
    # applying context for the payload
    payload = tpl.render(ctx)

    # init of Client
    client = HttpClient()

    headers = {
        "Content-type": "application/xml",
        "Accept": "application/xml"
    }

    # defining the URL needed fr the download
    url = f"{settings.OGC_SERVER['default']['LOCATION']}ows?service=WPS&version=1.0.0&REQUEST=Execute"
    if not request.user.is_anonymous:
        # define access token for the user
        access_token = get_or_create_token(request.user)
        url += f"&access_token={access_token}"

    # request to geoserver
    response, content = client.request(
        url=url,
        data=payload,
        method="post",
        headers=headers
    )

    if response.status_code != 200:
        logger.error(f"Download dataset exception: error during call with GeoServer: {response.content}")
        return JsonResponse(
            {"error": f"Download dataset exception: error during call with GeoServer: {response.content}"},
            status=500
        )

    # error handling
    namespaces = {"ows": "http://www.opengis.net/ows/1.1", "wps": "http://www.opengis.net/wps/1.0.0"}
    response_type = response.headers.get('Content-Type')
    if response_type == 'text/xml':
        # parsing XML for get exception
        content = ET.fromstring(response.text)
        exc = content.find('*//ows:Exception', namespaces=namespaces) or content.find('ows:Exception', namespaces=namespaces)
        if exc:
            exc_text = exc.find('ows:ExceptionText', namespaces=namespaces)
            logger.error(f"{exc.attrib.get('exceptionCode')} {exc_text.text}")
            return JsonResponse({"error": f"{exc.attrib.get('exceptionCode')}: {exc_text.text}"}, status=500)

    return_response = fetch_response_headers(
        HttpResponse(
            content=response.content,
            status=response.status_code,
            content_type=download_format
        ), response.headers)
    return_response.headers['Content-Type'] = download_format or _format
    return return_response