def test_launder(self):
     """Ensure the launder function works as expected.
     """
     self.assertEqual(launder('tm_world_borders_simpl_0.3'),
                      'tm_world_borders_simpl_0_3')
     self.assertEqual(launder('Testing#'), 'testing_')
     self.assertEqual(launder('   '), '_')
Example #2
0
def layer_create(request, template='upload/layer_create.html'):
    if request.method == 'POST':
        errors = False
        error_messages = []

        if request.is_ajax():
            configuration_options = json.loads(request.body)
        else:
            configuration_options = request.POST
            if isinstance(configuration_options.get('featureType', {}), str) \
                    or isinstance(configuration_options.get('featureType', {}), unicode):
                configuration_options['featureType'] = json.loads(
                    configuration_options['featureType'])

        if not configuration_options.get('layer_owner'):
            configuration_options['layer_owner'] = request.user

        if configuration_options['featureType'].get('editable') is True:
            configuration_options['storeCreateGeogig'] = True

        store_name = '{0}-layers'.format(request.user.username.lower())
        configuration_options['featureType']['store']['name'] = store_name

        # Launder the name of each attribute to ensure that there's no spaces or special characters,
        # as they will break the functionality of adding and editing features.
        for attribute in configuration_options['featureType']['attributes']['attribute']:
            attribute['name'] = launder(attribute['name'])

        creator = GeoServerLayerCreator()
        try:
            layers = creator.handle(
                configuration_options=configuration_options)

        except UploadError as e:
            errors = True
            error_messages.append(
                (configuration_options['featureType']['name'], e.message))

        if request.is_ajax():
            if errors:
                return HttpResponse(json.dumps({'status': 'failure', 'errors': error_messages}), status=400,
                                    content_type='application/json')
            if layers:
                layer_names = map(lambda layer: {'name': layer.name, 'url': layer.get_absolute_url()},
                                  Layer.objects.filter(name__in=[n[0] for n in layers]))

                return HttpResponse(json.dumps({'status': 'success', 'layers': layer_names}), status=201,
                                    content_type='application/json')

    return render_to_response(template, RequestContext(request, {}))
Example #3
0
    def import_file(self, *args, **kwargs):
        """
        Creates a Geoserver Layer from JSON.

        {
          "name": "a new layer",
          "store": {"name": "store"},
          "namespace": {"name": 'name'},
          "attributes": {"attribute": [
            {"name": "time",
             "binding": "org.geotools.data.postgis.PostGISDialect$XDate",
             "minOccurs": 0,
             "nillable": True},
           {"name": "geometry",
             "binding": "com.vividsolutions.jts.geom.MultiLineString",
             "minOccurs":0,
             "nillable":True}]},
          "nativeCRS": "EPSG:4326",
          "srs": "EPSG:4326"
        }
        """
        self.completed_layers = []
        configuration_options = kwargs.get('configuration_options')

        if not configuration_options:
            return

        # Configuration options should be a list at this point since the importer can process multiple layers in a
        # single import
        if isinstance(configuration_options, dict):
            configuration_options = [configuration_options]

        for layer in configuration_options:
            feature_type = layer.get('featureType')
            store_name = feature_type['store']['name']
            store_create_geogig = layer.get(u'storeCreateGeogig', 'false')
            owner = layer.get('layer_owner')
            username = owner.username
            email = owner.email
            layer['layer_type'] = 'vector'
            layer['fields'] = None
            layer['geoserver_store'] = {'type': 'geogig'}
            store = layer.get('geoserver_store')
            if store.get('type', str).lower() == 'geogig':
                name = slugify(feature_type['name'])
                store.setdefault('branch', 'master')
                store.setdefault('create', 'true')
                store.setdefault('name', name)
                store['geogig_repository'] = ("geoserver://%s" % name)
                store_name = name

            feature_type['title'] = feature_type['name']
            feature_type['name'] = launder(slugify(unicode(feature_type['name'])))

            # Without this check, the bounding box will default to 0, 0, -1, -1
            if 'nativeBoundingBox' not in feature_type:
                feature_type['nativeBoundingBox'] = {'minx': -180, 'maxx': 180, 'miny': -90, 'maxy': 90, 'crs': 'EPSG:4326'}

            if store_create_geogig and store_create_geogig != 'false':
                store_created = create_geoserver_db_featurestore(store_type='geogig', store_name=store_name, author_name=username,
                                                                 author_email=email)
                feature_type['store']['name'] = store_created.name

            if store_name not in getattr(settings, 'ALLOWED_DATASTORE_LAYER_CREATE', []) and '*' not in getattr(settings, 'ALLOWED_DATASTORE_LAYER_CREATE', []):
                return HttpResponseForbidden(content='Datastore specified in featureType is not in the ALLOWED_DATASTORE_LAYER_CREATE whitelist.')

            for x in range(0, 50):
                post_request = requests.post(
                    '{}/workspaces/{}/datastores/{}/featuretypes.json'.format(ogc_server_settings.rest, feature_type['namespace']['name'], store_name),
                    data='{{"featureType":{}}}'.format(json.dumps(feature_type)),
                    auth=ogc_server_settings.credentials,
                    headers={'content-type': 'application/json'}
                )
                if post_request.ok:
                    break
                if 'already exists in' in post_request.content:
                    break
                time.sleep(3)

            if post_request.ok:
                self.completed_layers.append([feature_type['name'], layer])
            else:
                message = 'Unable to create layer: {0}, an unhandled exception occurred.'.format(feature_type['name'])

                if 'already exists in' in post_request.content:
                    message = 'A layer named {0} already exists.  Please choose another name.'.format(feature_type['name'])
                print post_request.content
                raise UploadError(message)

        return self.completed_layers
Example #4
0
def layer_create(request, template='upload/layer_create.html'):
    if request.method == 'POST':
        errors = False
        error_messages = []

        if request.is_ajax():
            configuration_options = json.loads(request.body)
        else:
            configuration_options = request.POST
            if isinstance(configuration_options.get('featureType', {}), str) \
                    or isinstance(configuration_options.get('featureType', {}), unicode):
                configuration_options['featureType'] = json.loads(
                    configuration_options['featureType'])

        if not configuration_options.get('layer_owner'):
            configuration_options['layer_owner'] = request.user

        if configuration_options['featureType'].get('editable') is True:
            configuration_options['storeCreateGeogig'] = True

        store_name = '{0}-layers'.format(request.user.username.lower())
        configuration_options['featureType']['store']['name'] = store_name

        # Launder the name of each attribute to ensure that there's no spaces or special characters,
        # as they will break the functionality of adding and editing features.
        for attribute in configuration_options['featureType']['attributes'][
                'attribute']:
            attribute['name'] = launder(attribute['name'])

        creator = GeoServerLayerCreator()
        try:
            layers = creator.handle(
                configuration_options=configuration_options)

        except UploadError as e:
            errors = True
            error_messages.append(
                (configuration_options['featureType']['name'], e.message))

        if request.is_ajax():
            if errors:
                return HttpResponse(json.dumps({
                    'status': 'failure',
                    'errors': error_messages
                }),
                                    status=400,
                                    content_type='application/json')
            if layers:
                layer_names = map(
                    lambda layer: {
                        'name': layer.name,
                        'url': layer.get_absolute_url()
                    }, Layer.objects.filter(name__in=[n[0] for n in layers]))

                return HttpResponse(json.dumps({
                    'status': 'success',
                    'layers': layer_names
                }),
                                    status=201,
                                    content_type='application/json')

    return render_to_response(template, RequestContext(request, {}))
Example #5
0
    def import_file(self, *args, **kwargs):
        """
        Creates a Geoserver Layer from JSON.

        {
          "name": "a new layer",
          "store": {"name": "store"},
          "namespace": {"name": 'name'},
          "attributes": {"attribute": [
            {"name": "time",
             "binding": "org.geotools.data.postgis.PostGISDialect$XDate",
             "minOccurs": 0,
             "nillable": True},
           {"name": "geometry",
             "binding": "com.vividsolutions.jts.geom.MultiLineString",
             "minOccurs":0,
             "nillable":True}]},
          "nativeCRS": "EPSG:4326",
          "srs": "EPSG:4326"
        }
        """
        self.completed_layers = []
        configuration_options = kwargs.get('configuration_options')

        if not configuration_options:
            return

        # Configuration options should be a list at this point since the importer can process multiple layers in a
        # single import
        if isinstance(configuration_options, dict):
            configuration_options = [configuration_options]

        for layer in configuration_options:
            feature_type = layer.get('featureType')
            datastore = feature_type['store']['name']
            store_create_geogig = layer.get(u'storeCreateGeogig', 'false')

            feature_type['title'] = feature_type['name']
            feature_type['name'] = launder(slugify(unicode(feature_type['name'])))

            # Without this check, the bounding box will default to 0, 0, -1, -1
            if 'nativeBoundingBox' not in feature_type:
                feature_type['nativeBoundingBox'] = {'minx': -180, 'maxx': 180, 'miny': -90, 'maxy': 90, 'crs': 'EPSG:4326'}

            if store_create_geogig and store_create_geogig != 'false':
                store_created = create_geoserver_db_featurestore(store_type='geogig', store_name=feature_type['store']['name'])
                feature_type['store']['name'] = store_created.name

            if datastore not in getattr(settings, 'ALLOWED_DATASTORE_LAYER_CREATE', []) and '*' not in getattr(settings, 'ALLOWED_DATASTORE_LAYER_CREATE', []):
                return HttpResponseForbidden(content='Datastore specified in featureType is not in the ALLOWED_DATASTORE_LAYER_CREATE whitelist.')

            post_request = requests.post(
                '{}/workspaces/{}/datastores/{}/featuretypes.json'.format(ogc_server_settings.rest, feature_type['namespace']['name'], datastore),
                data='{{"featureType":{}}}'.format(json.dumps(feature_type)),
                auth=ogc_server_settings.credentials,
                headers={'content-type': 'application/json'}
            )

            if post_request.ok:
                self.completed_layers.append([feature_type['name'], layer])
            else:
                message = 'Unable to create layer: {0}, an unhandled exception occurred.'.format(feature_type['name'])

                if 'already exists in' in post_request.content:
                    message = 'A layer named {0} already exists.  Please choose another name.'.format(feature_type['name'])
                print post_request.content
                raise UploadError(message)

        return self.completed_layers