Esempio n. 1
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality('print_template', self.config,
                                      self.request)

        return self._info(templates)
Esempio n. 2
0
    def mobileconfig(self):
        """
        View callable for the mobile application's config.js file.
        """
        errors = set()
        interface = self.request.interface_name

        mobile_default_themes = get_functionality(
            'mobile_default_theme',
            self.settings,
            self.request
        )
        theme_name = self.request.params.get(
            'theme',
            mobile_default_themes[0] if len(mobile_default_themes) > 0 else None
        )
        user = self.request.user

        role_id = None if user is None else user.role.id
        themes, errors = self._themes(role_id, interface, False)

        for t in themes:
            self.flatten_layers(t)

        # comma-separated string including the feature types supported
        # by WFS service
        wfs_types, errors = self._internal_wfs_types(role_id)
        if len(errors) > 0:  # pragma: no cover
            raise HTTPBadGateway('\n'.join(errors))

        # info includes various information that is not used by config.js,
        # but by other - private to the integrator - parts of the mobile
        # application.
        info = {
            'username': user.username if user else ''
        }

        # get the list of themes available for mobile
        themes_ = []
        themes, errors = self._themes(role_id, interface, False)
        for theme in themes:
            # mobile theme or hidden theme explicitely loaded
            if theme['in_mobile_viewer'] or theme['name'] == theme_name:
                themes_.append({
                    'name': theme['name'],
                    'icon': theme['icon'],
                    'allLayers': theme['allLayers'],
                    'layers': theme['layers'],
                })

        self.request.response.content_type = 'application/javascript'
        self.request.response.headers["Vary"] = "Accept-Language"
        return {
            'lang': self.lang,
            'themes': themes_,
            'theme': theme_name if theme_name is not None else "",
            'wfs_types': wfs_types,
            'server_error': errors,
            'info': info,
        }
Esempio n. 3
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality(
            'print_template', self.config, self.request)

        return self._info(templates)
Esempio n. 4
0
 def _functionality(self):
     functionality = {}
     for func in get_setting(
             self.settings,
             ('functionalities', 'available_in_templates'), []):
         functionality[func] = get_functionality(
             func, self.settings, self.request)
     return functionality
Esempio n. 5
0
 def _functionality(self):
     functionality = {}
     for func in get_setting(self.settings,
                             ('functionalities', 'available_in_templates'),
                             []):
         functionality[func] = get_functionality(func, self.settings,
                                                 self.request)
     return functionality
Esempio n. 6
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality("print_template", self.config, self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.urlencode(params)

        return self._info(templates, query_string, self.request.method)
Esempio n. 7
0
 def _functionality_cached(self, role):
     functionality = {}
     for func in get_setting(
             self.settings,
             ("functionalities", "available_in_templates"), []
     ):
         functionality[func] = get_functionality(
             func, self.settings, self.request
         )
     return functionality
Esempio n. 8
0
    def mobileconfig(self):
        """
        View callable for the mobile application's config.js file.
        """
        errors = []

        mobile_default_themes = get_functionality('mobile_default_theme',
                                                  self.settings, self.request)
        theme_name = self.request.params.get(
            'theme', mobile_default_themes[0]
            if len(mobile_default_themes) > 0 else None)
        user = self.request.user

        role_id = None if user is None else user.role.id
        themes, errors = self._themes(role_id, True)

        for t in themes:
            self.flatten_layers(t)

        # comma-separated string including the feature types supported
        # by WFS service
        wfs_types, errors = self._internal_wfs_types()
        if len(errors) > 0:  # pragma: no cover
            raise HTTPBadGateway('\n'.join(errors))
        wfs_types = ','.join(wfs_types)

        # info includes various information that is not used by config.js,
        # but by other - private to the integrator - parts of the mobile
        # application.
        info = {'username': user.username if user else ''}

        # get the list of themes available for mobile
        themes_ = []
        themes, errors = self._themes(role_id, True)
        for theme in themes:
            # mobile theme or hidden theme explicitely loaded
            if theme['inMobileViewer'] or theme['name'] == theme_name:
                themes_.append({
                    'name': theme['name'],
                    'icon': theme['icon'],
                    'allLayers': theme['allLayers'],
                    'layers': theme['layers']
                })

        self.request.response.content_type = 'application/javascript'
        return {
            'lang': self.lang,
            'themes': json.dumps(themes_),
            'theme': theme_name if theme_name is not None else "",
            'wfs_types': wfs_types,
            'server_error': json.dumps(errors),
            'info': json.dumps(info)
        }
Esempio n. 9
0
    def capabilities(self):
        """ Get print capabilities. """

        templates = get_functionality("print_template", self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.urlencode(params)

        resp, content = self._capabilities(templates, query_string, self.request.method)

        return self._build_response(resp, content, PRIVATE_CACHE, "print")
Esempio n. 10
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality("print_template", self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.parse.urlencode(params)

        return self._info(
            templates,
            query_string,
            self.request.method,
        )
Esempio n. 11
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality('print_template', self.config,
                                      self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.urlencode(params)

        # get URL
        _url = self.config['print_url'] + 'info.json' + '?' + query_string
        log.info("Get print capabilities from %s." % _url)

        # forward request to target (without Host Header)
        http = httplib2.Http()
        h = dict(self.request.headers)
        if urlparse(_url).hostname != 'localhost':
            h.pop('Host')
        try:
            resp, content = http.request(_url, method='GET', headers=h)
        except:
            return HTTPBadGateway()

        try:
            capabilities = json.loads(content)
        except JSONDecodeError:
            # log and raise
            log.error("Unable to parse capabilities.")
            log.info(content)
            return content

        capabilities['layouts'] = list(layout
                                       for layout in capabilities['layouts']
                                       if layout['name'] in templates)

        headers = dict(resp)
        del headers['content-length']
        headers["Expires"] = "-1"
        headers["Pragma"] = "no-cache"
        headers["CacheControl"] = "no-cache"
        return Response(json.dumps(capabilities, separators=(',', ':')),
                        status=resp.status,
                        headers=headers)
Esempio n. 12
0
    def info(self):
        """ Get print capabilities. """

        templates = get_functionality(
            'print_template', self.config, self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.urlencode(params)

        # get URL
        _url = self.config['print_url'] + 'info.json' + '?' + query_string
        log.info("Get print capabilities from %s." % _url)

        # forward request to target (without Host Header)
        http = httplib2.Http()
        h = dict(self.request.headers)
        if urlparse(_url).hostname != 'localhost':
            h.pop('Host')
        try:
            resp, content = http.request(_url, method='GET', headers=h)
        except:
            return HTTPBadGateway()

        try:
            capabilities = json.loads(content)
        except JSONDecodeError:
            # log and raise
            log.error("Unable to parse capabilities.")
            log.info(content)
            return content

        capabilities['layouts'] = list(
            layout for layout in capabilities['layouts'] if
            layout['name'] in templates)

        headers = dict(resp)
        del headers['content-length']
        headers["Expires"] = "-1"
        headers["Pragma"] = "no-cache"
        headers["CacheControl"] = "no-cache"
        return Response(json.dumps(capabilities, separators=(',', ':')),
                        status=resp.status, headers=headers)
Esempio n. 13
0
    def capabilities(self):
        """ Get print capabilities. """

        templates = get_functionality("print_template", self.request)

        # get query string
        params = dict(self.request.params)
        query_string = urllib.parse.urlencode(params)

        resp, content = self._capabilities(
            templates,
            query_string,
            self.request.method,
        )

        return self._build_response(
            resp,
            content,
            PRIVATE_CACHE,
            "print",
        )
Esempio n. 14
0
    def test_functionalities(self):
        from tests.functional import create_dummy_request
        from c2cgeoportal.models import DBSession, User
        from c2cgeoportal.lib.functionality import get_functionality

        request = create_dummy_request()
        request.user = None
        request1 = create_dummy_request()
        request1.user = DBSession.query(User).filter(
            User.username == "__test_user1").one()
        request2 = create_dummy_request()
        request2.user = DBSession.query(User).filter(
            User.username == "__test_user2").one()

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {},
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEqual(get_functionality("__test_s", request), [])
        self.assertEqual(get_functionality("__test_a", request), [])
        self.assertEqual(get_functionality("__test_s", request1), [])
        self.assertEqual(get_functionality("__test_a", request1), [])
        self.assertEqual(get_functionality("__test_s", request2), ["db"])
        self.assertEqual(get_functionality("__test_a", request2),
                         ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEqual(get_functionality("__test_s", request), [])
        self.assertEqual(get_functionality("__test_a", request), [])
        self.assertEqual(get_functionality("__test_s", request1),
                         ["registered"])
        self.assertEqual(get_functionality("__test_a", request1), ["r1", "r2"])
        self.assertEqual(get_functionality("__test_s", request2), ["db"])
        self.assertEqual(get_functionality("__test_a", request2),
                         ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {}
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEqual(get_functionality("__test_s", request), ["anonymous"])
        self.assertEqual(get_functionality("__test_a", request), ["a1", "a2"])
        self.assertEqual(get_functionality("__test_s", request1),
                         ["anonymous"])
        self.assertEqual(get_functionality("__test_a", request1), ["a1", "a2"])
        self.assertEqual(get_functionality("__test_s", request2), ["db"])
        self.assertEqual(get_functionality("__test_a", request2),
                         ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEqual(get_functionality("__test_s", request), ["anonymous"])
        self.assertEqual(get_functionality("__test_a", request), ["a1", "a2"])
        self.assertEqual(get_functionality("__test_s", request1),
                         ["registered"])
        self.assertEqual(get_functionality("__test_a", request1), ["r1", "r2"])
        self.assertEqual(get_functionality("__test_s", request2), ["db"])
        self.assertEqual(get_functionality("__test_a", request2),
                         ["db1", "db2"])
Esempio n. 15
0
def proxy(request):

    user = request.user
    external = bool(request.params.get("EXTERNAL", None))

    # params hold the parameters we're going to send to MapServer
    params = dict(request.params)

    # reset possible value of role_id and user_id
    if 'role_id' in params:
        del params['role_id']
    if 'user_id' in params:
        del params['user_id']
    if user:
        # We have a user logged in. We need to set group_id and
        # possible layer_name in the params. We set layer_name
        # when either QUERY_PARAMS or LAYERS is set in the
        # WMS params, i.e. for GetMap and GetFeatureInfo
        # requests. For GetLegendGraphic requests we don't
        # send layer_name, but MapServer shouldn't use the DATA
        # string for GetLegendGraphic.

        params['role_id'] = user.parent_role.id if external else user.role.id

        # In some application we want to display the features owned by a user
        # than we need his id.
        if not external:
            params['user_id'] = user.id

    # don't allows direct variable substitution
    for k in params.keys():
        if k[:2].capitalize() == 'S_':
            log.warning("Direct substitution not allowed (%s=%s)." %
                        (k, params[k]))
            del params[k]

    mss = get_functionality('mapserver_substitution',
                            request.registry.settings, request)
    if mss:
        for s in mss:
            index = s.find('=')
            if index > 0:
                attribute = 's_' + s[:index]
                value = s[index + 1:]
                if attribute in params:
                    params[attribute] += "," + value
                else:
                    params[attribute] = value
            else:
                log.warning("Mapserver Substitution '%s' does not "
                            "respect pattern: <attribute>=<value>" % s)

    # get method
    method = request.method

    # we want the browser to cache GetLegendGraphic requests, so
    # we need to know if the current request is a GetLegendGraphic
    # request
    is_glg = False

    # name of the JSON callback (value for the "callback" query string param
    # in the request). None if request has no "callback" param in the query
    # string
    callback = None

    if method == "GET":
        _params = dict(
            (k.lower(), unicode(v).lower()) for k, v in params.iteritems())

        # For GET requests, params are added only if the REQUEST
        # parameter is actually provided.
        if 'request' not in _params:
            params = {}  # pragma: no cover
        else:
            # WMS GetLegendGraphic request?
            is_glg = ('service' not in _params or _params['service'] == u'wms') and \
                _params['request'] == u'getlegendgraphic'

        callback = params.get('callback')

    # get query string
    params_encoded = {}
    for k, v in params.iteritems():
        if k == 'callback':
            continue
        params_encoded[k] = unicode(v).encode('utf-8')
    query_string = urllib.urlencode(params_encoded)

    # get URL
    _url = request.registry.settings['external_mapserv_url'] \
        if external \
        else request.registry.settings['mapserv_url']
    _url += '?' + query_string
    log.info("Querying mapserver proxy at URL: %s." % _url)

    # get body
    body = None
    if method in ("POST", "PUT"):
        body = request.body

    # forward request to target (without Host Header)
    http = httplib2.Http()
    h = dict(request.headers)
    if urlparse(_url).hostname != 'localhost':
        h.pop('Host')
    # mapserver don't need the cookie, and sometimes it failed with it.
    if 'Cookie' in h:
        h.pop('Cookie')
    try:
        resp, content = http.request(_url, method=method, body=body, headers=h)
    except:  # pragma: no cover
        log.error("Error '%s' while getting the URL: %s." %
                  (sys.exc_info()[0], _url))
        if method == "POST":
            log.error("--- With body ---")
            log.error(body)
        return HTTPBadGateway("See logs for details")  # pragma: no cover

    if resp.status != 200:
        log.error("\nError\n '%s'\n in response from URL:\n %s\n "
                  "with query:\n %s" %
                  (resp.reason, _url, body))  # pragma: no cover
        return HTTPInternalServerError(
            "See logs for details")  # pragma: no cover

    # check for allowed content types
    if "content-type" not in resp:
        return HTTPNotAcceptable()  # pragma: no cover

    if method == "POST" and is_get_feature(request.body):
        content = limit_featurecollection(content, limit=200)

    content_type = None
    if callback:
        content_type = "application/javascript"
        # escape single quotes in the JavaScript string
        content = unicode(content.decode('utf8'))
        content = content.replace(u"'", ur"\'")
        content = u"%s('%s');" % (callback, u' '.join(content.splitlines()))
    else:
        content_type = resp["content-type"]

    headers = {"Content-Type": content_type}

    if is_glg:
        # 30min expiration for GetLegendGraphic
        headers.update({"Cache-Control": "public, max-age=1800"})

    return Response(content, status=resp.status, headers=headers)
Esempio n. 16
0
    def mobileconfig(self):
        """
        View callable for the mobile application's config.js file.
        """
        errors = []
        layer_info = []
        public_only = True

        mobile_default_themes = get_functionality(
            'mobile_default_theme',
            self.settings,
            self.request
        )
        theme_name = self.request.params.get(
            'theme',
            mobile_default_themes[0] if len(mobile_default_themes) > 0 else None
        )
        user = self.request.user

        if theme_name:
            role_id = None if user is None else user.role.id

            themes, errors = self._themes(role_id)
            themes = filter(lambda theme: theme['name'] == theme_name, themes)
            theme = themes[0] if len(themes) > 0 else None

            def process(node, layer_info, public_only=True):
                if 'children' in node:
                    for child_node in node['children']:
                        public_only = process(
                            child_node, layer_info, public_only)
                else:
                    layer_info.append(node)
                    public_only = public_only and node['public'] is True
                return public_only

            if theme is not None:
                public_only = process(theme, layer_info)

        # we only support WMS layers right now
        layer_info = filter(lambda li: li['type'] == 'internal WMS', layer_info)

        # comma-separated string including the names of layers of the
        # requested theme
        layers = ','.join(reversed([li['name'] for li in layer_info]))

        # comma-separated string including the names of layers that
        # should visible by default in the map
        visible_layers = filter(lambda li: li['isChecked'] is True, layer_info)
        visible_layers = ','.join(reversed([li['name'] for li in visible_layers]))

        # comma-separated string including the feature types supported
        # by WFS service
        wfs_types, errors = self._internal_wfs_types()
        if len(errors) > 0:
            raise HTTPBadGateway('\n'.join(errors))
        wfs_types = ','.join(wfs_types)

        # info includes various information that is not used by config.js,
        # but by other - private to the integrator - parts of the mobile
        # application.
        info = {
            'username': user.username if user else '',
            'publicLayersOnly': public_only
        }

        self.request.response.content_type = 'application/javascript'
        return {
            'lang': self.lang,
            'layers': layers,
            'visible_layers': visible_layers,
            'wfs_types': wfs_types,
            'server_error': json.dumps(errors),
            'info': json.dumps(info)
        }
    def test_functionalities(self):
        from c2cgeoportal.tests.functional import create_dummy_request
        from c2cgeoportal.models import DBSession, User
        from c2cgeoportal.lib.functionality import get_functionality

        request = create_dummy_request()
        request.user = None
        request1 = create_dummy_request()
        request1.user = DBSession.query(User).filter(User.username == "__test_user1").one()
        request2 = create_dummy_request()
        request2.user = DBSession.query(User).filter(User.username == "__test_user2").one()

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {},
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEquals(get_functionality("__test_s", request), [])
        self.assertEquals(get_functionality("__test_a", request), [])
        self.assertEquals(get_functionality("__test_s", request1), [])
        self.assertEquals(get_functionality("__test_a", request1), [])
        self.assertEquals(get_functionality("__test_s", request2), ["db"])
        self.assertEquals(get_functionality("__test_a", request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEquals(get_functionality("__test_s", request), [])
        self.assertEquals(get_functionality("__test_a", request), [])
        self.assertEquals(get_functionality("__test_s", request1), ["registered"])
        self.assertEquals(get_functionality("__test_a", request1), ["r1", "r2"])
        self.assertEquals(get_functionality("__test_s", request2), ["db"])
        self.assertEquals(get_functionality("__test_a", request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {}
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEquals(get_functionality("__test_s", request), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", request), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", request1), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", request1), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", request2), ["db"])
        self.assertEquals(get_functionality("__test_a", request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            },
            "admin_interface": {
                "available_functionalities": ["__test_a", "__test_s"]
            }
        }
        functionality.FUNCTIONALITIES_TYPES = None
        request.registry.settings.update(settings)
        request1.registry.settings.update(settings)
        request2.registry.settings.update(settings)
        self.assertEquals(get_functionality("__test_s", request), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", request), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", request1), ["registered"])
        self.assertEquals(get_functionality("__test_a", request1), ["r1", "r2"])
        self.assertEquals(get_functionality("__test_s", request2), ["db"])
        self.assertEquals(get_functionality("__test_a", request2), ["db1", "db2"])
Esempio n. 18
0
    def proxy(self):

        user = self.request.user
        external = bool(self.request.params.get("EXTERNAL", None))
        useSecurityMetadata = bool(self.request.registry.settings.get(
            'use_security_metadata', False
        ))

        # params hold the parameters we're going to send to MapServer
        params = dict(self.request.params)

        # reset possible value of role_id and user_id
        if 'role_id' in params:  # pragma: no cover
            del params['role_id']
        if 'user_id' in params:  # pragma: no cover
            del params['user_id']
        if user:
            # We have a user logged in. We need to set group_id and
            # possible layer_name in the params. We set layer_name
            # when either QUERY_PARAMS or LAYERS is set in the
            # WMS params, i.e. for GetMap and GetFeatureInfo
            # requests. For GetLegendGraphic requests we don't
            # send layer_name, but MapServer shouldn't use the DATA
            # string for GetLegendGraphic.

            params['role_id'] = user.parent_role.id if external else user.role.id

            # In some application we want to display the features owned by a user
            # than we need his id.
            if not external:
                params['user_id'] = user.id

        # don't allows direct variable substitution
        for k in params.keys():
            if k[:2].capitalize() == 'S_':
                log.warning("Direct substitution not allowed (%s=%s)." %
                            (k, params[k]))
                del params[k]

        # add protected layers enabling params
        if user and useSecurityMetadata:
            role_id = user.parent_role.id if external else user.role.id
            layers = self._get_protected_layers(role_id)
            _params = dict(
                (k.lower(), unicode(v).lower()) for k, v in params.iteritems()
            )
            if 'layers' in _params:
                # limit the list to queried layers
                l = []
                for layer in _params['layers'].split(','):
                    if layer in layers:
                        l.append(layer)
                layers = l
            for layer in layers:
                params['s_enable_' + str(layer)] = '*'

        # add functionalities params
        mss = get_functionality(
            'mapserver_substitution',
            self.request.registry.settings, self.request
        )
        if mss:
            for s in mss:
                index = s.find('=')
                if index > 0:
                    attribute = 's_' + s[:index]
                    value = s[index + 1:]
                    if attribute in params:
                        params[attribute] += "," + value
                    else:
                        params[attribute] = value
                else:
                    log.warning("Mapserver Substitution '%s' does not "
                                "respect pattern: <attribute>=<value>" % s)

        # get method
        method = self.request.method

        # we want the browser to cache GetLegendGraphic and
        # DescribeFeatureType requests
        use_cache = False

        if method == "GET":
            _params = dict(
                (k.lower(), unicode(v).lower()) for k, v in params.iteritems()
            )

            # For GET requests, params are added only if the self.request
            # parameter is actually provided.
            if 'request' not in _params:
                params = {}  # pragma: no cover
            else:
                # WMS GetLegendGraphic self.request?
                use_cache = ('service' not in _params or _params['service'] == u'wms') and \
                    _params['request'] == u'getlegendgraphic'

                if _params['service'] == u'wfs' and \
                        _params['request'] == u'describefeaturetype':
                    use_cache = True  # pragma: no cover

            if 'service' in _params and _params['service'] == u'wfs':
                _url = self._get_external_wfs_url() if external else self._get_wfs_url()
            else:
                _url = self.request.registry.settings['external_mapserv_url'] \
                    if external \
                    else self.request.registry.settings['mapserv_url']
        else:
            # POST means WFS
            _url = self._get_external_wfs_url() if external else self._get_wfs_url()

        if use_cache:
            return self._proxy_cache(_url, params, method, self.request.headers)
        else:
            return self._proxy(
                _url, params, use_cache, method, self.request.body,
                self.request.headers
            )
Esempio n. 19
0
def proxy(request):

    user = request.user
    external = bool(request.params.get("EXTERNAL", None))

    # params hold the parameters we're going to send to MapServer
    params = dict(request.params)

    # reset possible value of role_id and user_id
    if "role_id" in params:
        del params["role_id"]
    if "user_id" in params:
        del params["user_id"]
    if user:
        # We have a user logged in. We need to set group_id and
        # possible layer_name in the params. We set layer_name
        # when either QUERY_PARAMS or LAYERS is set in the
        # WMS params, i.e. for GetMap and GetFeatureInfo
        # requests. For GetLegendGraphic requests we don't
        # send layer_name, but MapServer shouldn't use the DATA
        # string for GetLegendGraphic.

        params["role_id"] = user.parent_role.id if external else user.role.id

        # In some application we want to display the features owned by a user
        # than we need his id.
        if not external:
            params["user_id"] = user.id

    # don't allows direct variable substitution
    for k in params.keys():
        if k[:2].capitalize() == "S_":
            log.warning("Direct substitution not allowed (%s=%s)." % (k, params[k]))
            del params[k]

    mss = get_functionality("mapserver_substitution", request.registry.settings, request)
    if mss:
        for s in mss:
            index = s.find("=")
            if index > 0:
                attribute = "s_" + s[:index]
                value = s[index + 1 :]
                if attribute in params:
                    params[attribute] += "," + value
                else:
                    params[attribute] = value
            else:
                log.warning("Mapserver Substitution '%s' does not " "respect pattern: <attribute>=<value>" % s)

    # get method
    method = request.method

    # we want the browser to cache GetLegendGraphic requests, so
    # we need to know if the current request is a GetLegendGraphic
    # request
    is_glg = False

    # name of the JSON callback (value for the "callback" query string param
    # in the request). None if request has no "callback" param in the query
    # string
    callback = None

    if method == "GET":
        _params = dict((k.lower(), unicode(v).lower()) for k, v in params.iteritems())

        # For GET requests, params are added only if the REQUEST
        # parameter is actually provided.
        if "request" not in _params:
            params = {}  # pragma: no cover
        else:
            # WMS GetLegendGraphic request?
            is_glg = ("service" not in _params or _params["service"] == u"wms") and _params[
                "request"
            ] == u"getlegendgraphic"

        callback = params.get("callback")

    # get query string
    params_encoded = {}
    for k, v in params.iteritems():
        if k == "callback":
            continue
        params_encoded[k] = unicode(v).encode("utf-8")
    query_string = urllib.urlencode(params_encoded)

    # get URL
    _url = request.registry.settings["external_mapserv_url"] if external else request.registry.settings["mapserv_url"]
    _url += "?" + query_string
    log.info("Querying mapserver proxy at URL: %s." % _url)

    # get body
    body = None
    if method in ("POST", "PUT"):
        body = request.body

    # forward request to target (without Host Header)
    http = httplib2.Http()
    h = dict(request.headers)
    if urlparse(_url).hostname != "localhost":
        h.pop("Host")
    # mapserver don't need the cookie, and sometimes it failed with it.
    if "Cookie" in h:
        h.pop("Cookie")
    try:
        resp, content = http.request(_url, method=method, body=body, headers=h)
    except:  # pragma: no cover
        log.error("Error '%s' while getting the URL: %s." % (sys.exc_info()[0], _url))
        if method == "POST":
            log.error("--- With body ---")
            log.error(body)
        return HTTPBadGateway("See logs for details")  # pragma: no cover

    if resp.status != 200:
        log.error(
            "\nError\n '%s'\n in response from URL:\n %s\n " "with query:\n %s" % (resp.reason, _url, body)
        )  # pragma: no cover
        return HTTPInternalServerError("See logs for details")  # pragma: no cover

    # check for allowed content types
    if "content-type" not in resp:
        return HTTPNotAcceptable()  # pragma: no cover

    if method == "POST" and is_get_feature(request.body):
        content = limit_featurecollection(content, limit=200)

    content_type = None
    if callback:
        content_type = "application/javascript"
        # escape single quotes in the JavaScript string
        content = unicode(content.decode("utf8"))
        content = content.replace(u"'", ur"\'")
        content = u"%s('%s');" % (callback, u" ".join(content.splitlines()))
    else:
        content_type = resp["content-type"]

    headers = {"Content-Type": content_type}

    if is_glg:
        # 30min expiration for GetLegendGraphic
        headers.update({"Cache-Control": "public, max-age=1800"})

    return Response(content, status=resp.status, headers=headers)
    def test_functionalities(self):
        from c2cgeoportal.tests.functional import create_dummy_request
        from c2cgeoportal.models import DBSession, User
        from c2cgeoportal.lib.functionality import get_functionality

        request = create_dummy_request()
        request.user = None
        request1 = create_dummy_request()
        request1.user = DBSession.query(User).filter(User.username == "__test_user1").one()
        request2 = create_dummy_request()
        request2.user = DBSession.query(User).filter(User.username == "__test_user2").one()

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {},
            }
        }
        self.assertEquals(get_functionality("__test_s", settings, request), [])
        self.assertEquals(get_functionality("__test_a", settings, request), [])
        self.assertEquals(get_functionality("__test_s", settings, request1), [])
        self.assertEquals(get_functionality("__test_a", settings, request1), [])
        self.assertEquals(get_functionality("__test_s", settings, request2), ["db"])
        self.assertEquals(get_functionality("__test_a", settings, request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {},
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            }
        }
        self.assertEquals(get_functionality("__test_s", settings, request), [])
        self.assertEquals(get_functionality("__test_a", settings, request), [])
        self.assertEquals(get_functionality("__test_s", settings, request1), ["registered"])
        self.assertEquals(get_functionality("__test_a", settings, request1), ["r1", "r2"])
        self.assertEquals(get_functionality("__test_s", settings, request2), ["db"])
        self.assertEquals(get_functionality("__test_a", settings, request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {}
            }
        }
        self.assertEquals(get_functionality("__test_s", settings, request), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", settings, request), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", settings, request1), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", settings, request1), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", settings, request2), ["db"])
        self.assertEquals(get_functionality("__test_a", settings, request2), ["db1", "db2"])

        settings = {
            "functionalities": {
                "anonymous": {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                "registered": {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            }
        }
        self.assertEquals(get_functionality("__test_s", settings, request), ["anonymous"])
        self.assertEquals(get_functionality("__test_a", settings, request), ["a1", "a2"])
        self.assertEquals(get_functionality("__test_s", settings, request1), ["registered"])
        self.assertEquals(get_functionality("__test_a", settings, request1), ["r1", "r2"])
        self.assertEquals(get_functionality("__test_s", settings, request2), ["db"])
        self.assertEquals(get_functionality("__test_a", settings, request2), ["db1", "db2"])
Esempio n. 21
0
    def test_functionalities(self):
        from c2cgeoportal.tests.functional import createDummyRequest
        from c2cgeoportal.models import DBSession, User
        from c2cgeoportal.lib.functionality import get_functionality

        request = createDummyRequest()
        request.user = None
        request1 = createDummyRequest()
        request1.user = DBSession.query(User).filter(User.username == '__test_user1').one()
        request2 = createDummyRequest()
        request2.user = DBSession.query(User).filter(User.username == '__test_user2').one()

        settings = {
            'functionalities': {
                'anonymous': {},
                'registered': {},
            }
        }
        self.assertEquals(get_functionality('__test_s', settings, request), [])
        self.assertEquals(get_functionality('__test_a', settings, request), [])
        self.assertEquals(get_functionality('__test_s', settings, request1), [])
        self.assertEquals(get_functionality('__test_a', settings, request1), [])
        self.assertEquals(get_functionality('__test_s', settings, request2), ['db'])
        self.assertEquals(get_functionality('__test_a', settings, request2), ['db1', 'db2'])

        settings = {
            'functionalities': {
                'anonymous': {},
                'registered': {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            }
        }
        self.assertEquals(get_functionality('__test_s', settings, request), [])
        self.assertEquals(get_functionality('__test_a', settings, request), [])
        self.assertEquals(get_functionality('__test_s', settings, request1), ['registered'])
        self.assertEquals(get_functionality('__test_a', settings, request1), ['r1', 'r2'])
        self.assertEquals(get_functionality('__test_s', settings, request2), ['db'])
        self.assertEquals(get_functionality('__test_a', settings, request2), ['db1', 'db2'])

        settings = {
            'functionalities': {
                'anonymous': {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                'registered': {}
            }
        }
        self.assertEquals(get_functionality('__test_s', settings, request), ['anonymous'])
        self.assertEquals(get_functionality('__test_a', settings, request), ['a1', 'a2'])
        self.assertEquals(get_functionality('__test_s', settings, request1), ['anonymous'])
        self.assertEquals(get_functionality('__test_a', settings, request1), ['a1', 'a2'])
        self.assertEquals(get_functionality('__test_s', settings, request2), ['db'])
        self.assertEquals(get_functionality('__test_a', settings, request2), ['db1', 'db2'])

        settings = {
            'functionalities': {
                'anonymous': {
                    "__test_s": "anonymous",
                    "__test_a": ["a1", "a2"]
                },
                'registered': {
                    "__test_s": "registered",
                    "__test_a": ["r1", "r2"]
                }
            }
        }
        self.assertEquals(get_functionality('__test_s', settings, request), ['anonymous'])
        self.assertEquals(get_functionality('__test_a', settings, request), ['a1', 'a2'])
        self.assertEquals(get_functionality('__test_s', settings, request1), ['registered'])
        self.assertEquals(get_functionality('__test_a', settings, request1), ['r1', 'r2'])
        self.assertEquals(get_functionality('__test_s', settings, request2), ['db'])
        self.assertEquals(get_functionality('__test_a', settings, request2), ['db1', 'db2'])
Esempio n. 22
0
    def mobileconfig(self):
        """
        View callable for the mobile application's config.js file.
        """
        errors = set()
        interface = self.request.interface_name

        mobile_default_themes = get_functionality(
            "mobile_default_theme",
            self.settings,
            self.request
        )
        theme_name = self.request.params.get(
            "theme",
            mobile_default_themes[0] if len(mobile_default_themes) > 0 else None
        )
        user = self.request.user

        role_id = None if user is None else user.role.id
        themes, errors = self._themes(role_id, interface, False)

        for t in themes:
            self.flatten_layers(t)

        # comma-separated string including the feature types supported
        # by WFS service
        wfs_types, errors = self._internal_wfs_types(role_id)
        if len(errors) > 0:  # pragma: no cover
            raise HTTPBadGateway("\n".join(errors))

        # info includes various information that is not used by config.js,
        # but by other - private to the integrator - parts of the mobile
        # application.
        info = {
            "username": user.username if user else ""
        }

        # get the list of themes available for mobile
        themes_ = []
        themes, errors = self._themes(role_id, interface, False)
        for theme in themes:
            # mobile theme or hidden theme explicitely loaded
            if theme["in_mobile_viewer"] or theme["name"] == theme_name:
                themes_.append({
                    "name": theme["name"],
                    "icon": theme["icon"],
                    "allLayers": theme["allLayers"],
                    "layers": theme["layers"],
                })

        set_common_headers(
            self.request, "sencha_config", PRIVATE_CACHE,
            vary=True, content_type="application/javascript",
        )

        return {
            "lang": self.lang,
            "themes": themes_,
            "theme": theme_name if theme_name is not None else "",
            "wfs_types": wfs_types,
            "server_error": errors,
            "info": info,
        }
Esempio n. 23
0
    def proxy(self):

        user = self.request.user
        external = bool(self.request.params.get("EXTERNAL", None))

        # params hold the parameters we're going to send to MapServer
        params = dict(self.request.params)

        # reset possible value of role_id and user_id
        if 'role_id' in params:  # pragma: no cover
            del params['role_id']
        if 'user_id' in params:  # pragma: no cover
            del params['user_id']
        if user:
            # We have a user logged in. We need to set group_id and
            # possible layer_name in the params. We set layer_name
            # when either QUERY_PARAMS or LAYERS is set in the
            # WMS params, i.e. for GetMap and GetFeatureInfo
            # requests. For GetLegendGraphic requests we don't
            # send layer_name, but MapServer shouldn't use the DATA
            # string for GetLegendGraphic.

            params[
                'role_id'] = user.parent_role.id if external else user.role.id

            # In some application we want to display the features owned by a user
            # than we need his id.
            if not external:
                params['user_id'] = user.id

        # don't allows direct variable substitution
        for k in params.keys():
            if k[:2].capitalize() == 'S_':
                log.warning("Direct substitution not allowed (%s=%s)." %
                            (k, params[k]))
                del params[k]

        # add protected layers enabling params
        if user:
            role_id = user.parent_role.id if external else user.role.id
            layers = self._get_protected_layers(role_id)
            _params = dict(
                (k.lower(), unicode(v).lower()) for k, v in params.iteritems())
            if 'layers' in _params:
                # limit the list to queried layers
                l = []
                for layer in _params['layers'].split(','):
                    if layer in layers:
                        l.append(layer)
                layers = l
            for layer in layers:
                params['s_enable_' + str(layer)] = '*'

        # add functionalities params
        mss = get_functionality('mapserver_substitution',
                                self.request.registry.settings, self.request)
        if mss:
            for s in mss:
                index = s.find('=')
                if index > 0:
                    attribute = 's_' + s[:index]
                    value = s[index + 1:]
                    if attribute in params:
                        params[attribute] += "," + value
                    else:
                        params[attribute] = value
                else:
                    log.warning("Mapserver Substitution '%s' does not "
                                "respect pattern: <attribute>=<value>" % s)

        # get method
        method = self.request.method

        # we want the browser to cache GetLegendGraphic and
        # DescribeFeatureType requests
        use_cache = False

        if method == "GET":
            _params = dict(
                (k.lower(), unicode(v).lower()) for k, v in params.iteritems())

            # For GET requests, params are added only if the self.request
            # parameter is actually provided.
            if 'request' not in _params:
                params = {}  # pragma: no cover
            else:
                # WMS GetLegendGraphic self.request?
                use_cache = ('service' not in _params or _params['service'] == u'wms') and \
                    _params['request'] == u'getlegendgraphic'

                if _params['service'] == u'wfs' and \
                        _params['request'] == u'describefeaturetype':
                    use_cache = True  # pragma: no cover

            if 'service' in _params and _params['service'] == u'wfs':
                _url = self._get_external_wfs_url(
                ) if external else self._get_wfs_url()
            else:
                _url = self.request.registry.settings['external_mapserv_url'] \
                    if external \
                    else self.request.registry.settings['mapserv_url']
        else:
            # POST means WFS
            _url = self._get_external_wfs_url(
            ) if external else self._get_wfs_url()

        if use_cache:
            return self._proxy_cache(_url, params, method,
                                     self.request.headers)
        else:
            return self._proxy(_url, params, use_cache, method,
                               self.request.body, self.request.headers)
Esempio n. 24
0
    def mobileconfig(self):
        """
        View callable for the mobile application's config.js file.
        """
        errors = []
        layer_info = []
        public_only = True

        mobile_default_themes = get_functionality('mobile_default_theme',
                                                  self.settings, self.request)
        theme_name = self.request.params.get(
            'theme', mobile_default_themes[0]
            if len(mobile_default_themes) > 0 else None)
        user = self.request.user

        if theme_name:
            role_id = None if user is None else user.role.id

            themes, errors = self._themes(role_id)
            themes = filter(lambda theme: theme['name'] == theme_name, themes)
            theme = themes[0] if len(themes) > 0 else None

            def process(node, layer_info, public_only=True):
                if 'children' in node:
                    for child_node in node['children']:
                        public_only = process(child_node, layer_info,
                                              public_only)
                else:
                    layer_info.append(node)
                    public_only = public_only and node['public'] is True
                return public_only

            if theme is not None:
                public_only = process(theme, layer_info)

        # we only support WMS layers right now
        layer_info = filter(lambda li: li['type'] == 'internal WMS',
                            layer_info)

        # comma-separated string including the names of layers of the
        # requested theme
        layers = ','.join(reversed([li['name'] for li in layer_info]))

        # comma-separated string including the names of layers that
        # should visible by default in the map
        visible_layers = filter(lambda li: li['isChecked'] is True, layer_info)
        visible_layers = ','.join(
            reversed([li['name'] for li in visible_layers]))

        # comma-separated string including the feature types supported
        # by WFS service
        wfs_types, errors = self._internal_wfs_types()
        if len(errors) > 0:
            raise HTTPBadGateway('\n'.join(errors))
        wfs_types = ','.join(wfs_types)

        # info includes various information that is not used by config.js,
        # but by other - private to the integrator - parts of the mobile
        # application.
        info = {
            'username': user.username if user else '',
            'publicLayersOnly': public_only
        }

        self.request.response.content_type = 'application/javascript'
        return {
            'lang': self.lang,
            'layers': layers,
            'visible_layers': visible_layers,
            'wfs_types': wfs_types,
            'server_error': json.dumps(errors),
            'info': json.dumps(info)
        }