Exemplo n.º 1
0
def fill_data():
    if not user_exists('cli'):
        create_user('cli', 'cli')
    cloud = Cloud({"app": current_app, "user": "******"})
    name = "elo layr"
    geom_type = "MULTIPOLYGON"
    fields = [{
        'name': 'geometry',
        'type': 'geometry(MULTIPOLYGON, 4326)'
    }, {
        'name': 'test',
        'type': 'character varying'
    }]
    cloud.create_layer(name, fields, geom_type)
    layer = Layer({"app": current_app, "user": "******", "name": "polygon layer"})
    TEST_DATA_PATH = op.join(op.dirname(op.abspath(__file__)), '..', 'tests',
                             'layers', 'correct_feature.json')
    data = json.loads(open(TEST_DATA_PATH).read())
    geometry = 'SRID=4326;{}'.format(shape(data['geometry']).wkt)
    columns = []
    values = []
    for k, v in data['properties'].items():
        if k in layer.columns():
            columns.append(k)
            values.append(v)
    layer.add_feature(columns, values)
Exemplo n.º 2
0
def attachments_post():

    added_at = datetime.now()
    result = []

    payload = request.get_json(force=True)

    layer_id = request.args.get("layer_id")
    feature_id = request.args.get("feature_id")

    files = payload["data"]

    with current_app._db.atomic():
        for file_ in files:
            name = file_["name"]
            content = file_["content"]

            try:
                content = b64decode(content.encode())
            except binascii.Error:
                return jsonify(
                    {"error": f"error decoding content of file '{name}'"}), 400

            if (layer_id is not None) and (feature_id is not None):

                try:
                    layer = Layer({
                        "app": current_app,
                        "user": request.user,
                        "lid": layer_id
                    })
                    layer.check_write()
                except PermissionError as e:
                    return jsonify({"error": str(e)}), 403
                try:
                    manager = LayerAttachmentsManager.from_layer(layer)
                except LayerNotSupportedError as e:
                    return jsonify({"error": str(e)}), 400

            created = Attachment.create_attachment(name, content, request.user,
                                                   added_at)
            result.append({
                "original_file_name": name,
                "saved_as": created.file_name,
                "attachment_id": created.id
            })

            if (layer_id is not None) and (feature_id is not None):
                for row in result:
                    manager.add_attachment_to_object(feature_id,
                                                     row["attachment_id"])

    return jsonify({"data": result}), 201
Exemplo n.º 3
0
def projects_post():
    user_name = request.user

    data = request.get_json(force=True)
    data["owner_name"] = user_name

    active_layer_id = data["active_layer_id"]
    additional_layers_ids = data.get('additional_layers_ids', [])

    layers_ids = additional_layers_ids + [active_layer_id]

    for layer_id in layers_ids:
        try:
            Layer(
                {"app": current_app, "user": user_name, "lid": layer_id})
        except ValueError as e:
            return jsonify({"error": f"layer {layer_id} does not exist"}), 400
        except PermissionError as e:
            return jsonify({"error": f"permission denied to layer {layer_id}"}), 403

    map_center = data["map_center"]
    data["map_center"] = fn.ST_GeomFromGeoJSON(json.dumps(map_center))

    project = Project(**data)
    project.save()

    return jsonify({"data": project.id}), 201
Exemplo n.º 4
0
def attachments_metadata_get():

    ids = request.args.get("ids")

    if (ids is not None) and (ids != ""):
        ids = ids.split(",")
    else:
        ids = []

    layer_id = request.args.get("layer_id")
    feature_id = request.args.get("feature_id")

    query = Attachment.select()
    if len(ids) > 0:
        query = query.where(Attachment.id.in_(ids))

    if (layer_id is not None) and (feature_id is not None):

        layer = Layer({
            "app": current_app,
            "user": request.user,
            "lid": layer_id
        })
        try:
            manager = LayerAttachmentsManager.from_layer(layer)
        except LayerNotSupportedError as e:
            return jsonify({"error": str(e)}), 400

        attachments_ids = manager.get_attachments_ids_of_object(feature_id)
        query = query.where(Attachment.id.in_(attachments_ids))

    result = list(query.dicts())
    return jsonify({"data": result})
Exemplo n.º 5
0
def does_user_have_permission_to_active_layer(user_name: str,
                                              project: Project) -> bool:
    layer_id = project.active_layer_id

    try:
        Layer({"app": current_app, "user": user_name, "lid": layer_id})
    except (PermissionError, ValueError):
        return False

    return True
Exemplo n.º 6
0
def does_user_have_permission_to_each_additional_layer(
        user_name: str, project: Project) -> bool:
    layers_ids = project.additional_layers_ids

    for layer_id in layers_ids:
        try:
            Layer({"app": current_app, "user": user_name, "lid": layer_id})
        except (PermissionError, ValueError):
            return False

    return True
Exemplo n.º 7
0
def attachments_delete():

    ids = request.args.get("ids", "")
    ids = ids.split(",")

    layer_id = request.args.get("layer_id")
    feature_id = request.args.get("feature_id")

    if len(ids) == 0 or ids == [""]:
        return jsonify({"error": "at least one ID is required"}), 400

    attachments = Attachment.select().where(Attachment.id.in_(ids))

    with current_app._db.atomic():

        if (layer_id is not None) and (feature_id is not None):

            try:
                layer = Layer({
                    "app": current_app,
                    "user": request.user,
                    "lid": layer_id
                })
                layer.check_write()
            except PermissionError as e:
                return jsonify({"error": str(e)}), 403
            try:
                manager = LayerAttachmentsManager.from_layer(layer)
            except LayerNotSupportedError as e:
                return jsonify({"error": str(e)}), 400

            for a in attachments:
                manager.remove_attachment_from_object(feature_id, a.id)

        for a in attachments:
            a.delete_instance()

    return jsonify({}), 204
Exemplo n.º 8
0
 def wrapper(*args, **kwargs):
     try:
         layer = Layer({
             "app": current_app,
             "user": request.user,
             "lid": kwargs.get('lid')
         })
         if permission == "owner":
             layer.check_owner()
         if permission == 'write':
             layer.check_write()
     except ValueError as e:
         return jsonify({"error": str(e)}), 401
     except PermissionError as e:
         return jsonify({"error": str(e)}), 403
     kwargs['layer'] = layer
     return func(*args, **kwargs)
Exemplo n.º 9
0
def projects_project_id_put(project_id: int):
    user_name = request.user

    project = Project.get_or_none(Project.id == project_id)

    if project is None:
        return jsonify({"error": "project does not exist"}), 404

    if not is_admin(user_name):
        if project.owner_name != user_name:
            return jsonify({"error": "permission denied to other users projects"}), 403

    data = request.get_json(force=True)

    data.pop("owner_name", None)

    active_layer_id = data.get("active_layer_id")
    additional_layers_ids = data.get('additional_layers_ids', [])

    layers_ids = additional_layers_ids
    if active_layer_id is not None:
        layers_ids.append(active_layer_id)

    for layer_id in layers_ids:
        try:
            Layer(
                {"app": current_app, "user": user_name, "lid": layer_id})
        except ValueError as e:
            return jsonify({"error": f"layer {layer_id} does not exist"}), 400
        except PermissionError as e:
            return jsonify({"error": f"permission denied to layer {layer_id}"}), 403

    map_center = data["map_center"]
    data["map_center"] = fn.ST_GeomFromGeoJSON(json.dumps(map_center))

    Project.update(**data).where(Project.id == project_id).execute()
    return jsonify({}), 204
Exemplo n.º 10
0
def get_xlsx(layer: Layer, feature_id: int, buffer_distance: float,
             feature_name: str) -> NamedTemporaryFile:
    distances = layer.get_distances(feature_id, buffer_distance)

    title_rows = [["Nazwa warstwy: ", layer.name],
                  ["Nazwa obiektu: ", feature_name]]

    workbook = openpyxl.Workbook()
    sheet = workbook.active

    sheet.column_dimensions["A"].width = 50
    sheet.column_dimensions["B"].width = 25

    for title in title_rows:
        sheet.append(title)

    sheet.append([])

    distances = distances["pn"] + distances["pk"]
    distances_headers = ["Forma ochrony przyrody", "Odległość [km]"]
    sheet.append(distances_headers)
    for dist in distances:
        object_name = dist["name"]
        distance = dist["distance"]

        distance_km = distance / 1000

        sheet.append([object_name, round(distance_km, 2)])

    result = NamedTemporaryFile()
    workbook.save(result.name)

    for row_number in range(1, sheet.max_row):
        sheet.row_dimensions[row_number] = 30

    return result
Exemplo n.º 11
0
 def does_layer_have_attachments_column(cls, layer: Layer) -> bool:
     columns = layer.columns()
     return ATTACHMENTS_COLUMN_NAME in columns
Exemplo n.º 12
0
def layers(cloud):
    if request.method == 'GET':
        return jsonify({"layers": cloud.get_layers()})
    elif request.method == 'POST':
        files = [request.files[f] for f in request.files]
        if not files:
            return jsonify({"error": "file is required"}), 401
        name = request.form.get("name")
        environ['SHAPE_ENCODING'] = request.form.get("encoding", 'utf-8')
        if not name:
            return jsonify({"error": "name is required"}), 401
        if cloud.layer_exists(name):
            return jsonify({"error": "layer already exists"}), 401

        if len(name) > MAX_LAYER_NAME_LENGTH:
            return jsonify({
                "error":
                f"character limit for table name exceeded ({MAX_LAYER_NAME_LENGTH})"
            }), 400

        temp_path = tempfile.mkdtemp()
        file_paths = []
        for f in files:
            file_path = op.join(temp_path, f.filename)
            f.save(file_path)
            file_paths.append(file_path)
        if len(file_paths) == 1:
            source = ogr.Open(file_paths[0], 0)
        else:
            for path in file_paths:
                try:
                    source = ogr.Open(path, 0)
                    if source:
                        break
                except:
                    continue
            else:
                return jsonify({"error": "file is invalid"}), 401
        layer = source.GetLayer()
        sref = layer.GetSpatialRef()
        epsg = None
        if sref:
            # Autodetect
            epsg = sref.GetAuthorityCode(None)
        if not epsg:
            # Get from request
            epsg = request.form.get("epsg", None)
        transform = None
        if epsg != "4326":
            if not epsg:
                return jsonify({"error": "epsg not recognized"}), 400
            inSpatialRef = osr.SpatialReference()
            inSpatialRef.ImportFromEPSG(int(epsg))
            inSpatialRef.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER)
            outSpatialRef = osr.SpatialReference()
            outSpatialRef.ImportFromEPSG(4326)
            outSpatialRef.SetAxisMappingStrategy(
                osr.OAMS_TRADITIONAL_GIS_ORDER)
            transform = osr.CoordinateTransformation(inSpatialRef,
                                                     outSpatialRef)
        ldefn = layer.GetLayerDefn()
        test_feature = layer.GetNextFeature()
        geom_type = test_feature.GetGeometryRef().GetGeometryName()
        layer.ResetReading()
        fields = [{
            "name": "geometry",
            "type": "geometry"  # Mixed content for shapefiles if geom_type set
        }]
        for n in range(ldefn.GetFieldCount()):
            fdefn = ldefn.GetFieldDefn(n)
            # RL-38 double id column
            if fdefn.name in set(map(lambda x: x['name'],
                                     fields)).union(set(['id'])):
                fdefn.name = f'_{fdefn.name}'
            fields.append({
                'name': fdefn.name,
                'type': GDAL_TO_PG[fdefn.GetTypeName()],
            })
        with current_app._db.atomic():
            cloud = Cloud({"app": current_app, "user": request.user})
            columns = list(map(lambda f: f['name'], fields))
            if ATTACHMENTS_COLUMN_NAME in columns:
                return jsonify({"error": "layer has attachemnts column"}), 400
            cloud.create_layer(name, fields, geom_type)
            with tempfile.SpooledTemporaryFile(mode='w') as tfile:
                count_features = 0
                for feature in layer:
                    the_geom = feature.GetGeometryRef()

                    if the_geom is None:
                        return jsonify({
                            "error":
                            "layer has at least one feature with empty geometry"
                        }), 400

                    if transform:
                        the_geom.Transform(transform)

                    ewkt = f"SRID=4326;{the_geom.ExportToWkt()}"

                    feature_string = ''
                    if len(columns) == 1:
                        # W przypadku braku atrybutów
                        feature_string += ewkt + "\n"
                    else:
                        for idx, column in enumerate(columns):
                            # Pierwszy wiersz to geometria
                            if idx == 0:
                                feature_string += ewkt + "\t"
                            else:
                                field = feature.GetField(column)
                                if isinstance(field, str):
                                    field = " ".join(field.split())
                                if idx + 1 != len(columns):
                                    feature_string += f'{field}\t'
                                else:
                                    feature_string += f'{field}\n'
                    count_features += 1
                    try:
                        tfile.write(feature_string)
                    except UnicodeEncodeError:
                        tfile.write(
                            feature_string.encode('utf8', 'replace').decode(
                                'utf8', 'replace'))
                tfile.seek(0)
                cur = current_app._db.cursor()
                cur.copy_from(tfile,
                              '"{}"'.format(name),
                              null='None',
                              columns=list(
                                  map(lambda c: '"{}"'.format(c), columns)))

            layer = Layer({
                "app": current_app,
                "user": request.user,
                "name": name
            })
            LayerAttachmentsManager.create_attachments_column(layer)
            layer.create_transform_index()

        return jsonify({
            "layers": {
                "name": layer.name,
                "features": layer.count(),
                "id": layer.lid
            }
        }), 201