Beispiel #1
0
def overview(subgraph_id):
    user_id = g.user['id']

    db = get_db()

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    subgraph = db.execute('SELECT * FROM subgraph WHERE id = ?',
                          (subgraph_id, )).fetchone()

    if subgraph is None:
        message = '{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id)
        return redirect(url_for('tool.index', message=quote(message)))

    if not subgraph_access(user_id, subgraph_id) and not subgraph['finished']:
        message = 'You have no access to {} with id {}.'.format(
            current_app.config['FRONTEND_CONFIG']['subgraph_term'],
            subgraph_id)
        return redirect(url_for('tool.index', message=quote(message)))

    return render_template(
        'tool/overview.html',
        subgraph=subgraph,
        rdf_graph=get_subgraph_knowledge(subgraph_id).get_graph(clean=True,
                                                                ontology=True))
Beispiel #2
0
def edit_view(subgraph_id):
    """Edit view.
    Displays knowledge about a subgraph and allows users to edit it."""
    user_id = g.user['id']

    db = get_db()

    subgraph = db.execute('SELECT * FROM subgraph WHERE id = ?',
                          (subgraph_id, )).fetchone()

    if subgraph is None:
        message = '{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id)
        # for some reason I need to unquote two times (once via url_for, once via quote) on the server, else
        # I'd get a bad request
        return redirect(url_for('tool.index', message=quote(message)))

    if not subgraph_access(user_id, subgraph_id):
        if subgraph['finished']:
            return redirect(
                url_for('tool.read_only_view', subgraph_id=subgraph_id))
        else:
            message = 'You have no access to {} with id {}.'.format(
                current_app.config['FRONTEND_CONFIG']['subgraph_term'],
                subgraph_id)
            return redirect(url_for('tool.index', message=quote(message)))

    root = get_subgraph_knowledge(subgraph_id).get_root()

    return render_template('tool/edit.html',
                           subgraph=subgraph,
                           root=root,
                           read_only=False)
Beispiel #3
0
def undo_delete_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    # TODO actually we should check whether restoring the information would violate any
    #  functional property constraints, but that would be very complicated and currently we
    #  have no described functional deletable entities where that could happen

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    subgraph_knowledge.undo_delete_individual(entity_uri)

    return jsonify()
Beispiel #4
0
def delete_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if not subgraph_knowledge.is_individual_deletable(entity_uri):
        return jsonify(error='You are not allowed to delete this entity.')

    deleted = subgraph_knowledge.delete_individual_recursive(entity_uri)

    if property_uri:
        is_functional = get_ontology().is_property_functional(property_uri)
        return jsonify(deleted=deleted, functional=is_functional)

    return jsonify(deleted=deleted)
Beispiel #5
0
def change_label():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    label = request.json.get('label')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')
    if not label or label.isspace():
        return jsonify(error='Label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if not subgraph_knowledge.is_individual_deletable(entity_uri):
        return jsonify(
            error='You are not allowed to change the label of this entity.')

    subgraph_knowledge.change_label(entity_uri, label.strip())

    return jsonify()
Beispiel #6
0
def change_value():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')
    index = request.json.get('index')
    value = request.json.get('value').strip()

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not entity_uri or entity_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if index is None:
        return jsonify(error='Index cannot be empty.')
    try:
        index = int(index)
    except ValueError:
        return jsonify(error='Index has to be an integer.')
    if value is None:
        return jsonify(error='Value cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)

    if get_ontology().is_property_described(property_uri):
        return jsonify(
            error=
            'You have to use /_change_label to change the label of a described individual'
        )

    if index == subgraph_knowledge.get_property_free_index(
            entity_uri, property_uri):
        subgraph_knowledge.new_value(entity_uri, property_uri)
    validity = subgraph_knowledge.change_value(entity_uri, property_uri, index,
                                               value.strip())
    if validity:
        return jsonify(validity=validity)

    return jsonify()
Beispiel #7
0
def delete_subgraph():
    """Marks a subgraph as deleted.

    The subgraph is not actually deleted from the db and can be made accessible again by setting the
    deleted flag back to 0.

    Request args:
        subgraph_id (int): Id of the Subgraph to delete.

    Context:
        g.user (sqlite3.Row): Logged in user. Must have access to the subgraph.

    Returns JSON:
        name (str): The new name of the deleted subgraph.
        error (str): An error message if something went wrong.

    """
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    db = get_db()
    db_cursor = db.cursor()

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id, user_id))

    subgraph_name = db_cursor.execute('SELECT name FROM subgraph WHERE id = ?',
                                      (subgraph_id, )).fetchone()[0]

    db_cursor.execute('UPDATE subgraph SET deleted = 1 WHERE id = ?',
                      (subgraph_id, ))

    db.commit()

    return jsonify(name=subgraph_name)
Beispiel #8
0
def edit_subgraph_name():
    """Changes the name of a subgraph.

    Request args:
        subgraph_id (int): Id of the Subgraph to change.
        name (str): The new name of the subgraph.

    Context:
        g.user (sqlite3.Row): Logged in user. Must have access to the subgraph.

    Returns JSON:
        name (str): The new name of the subgraph. (identical to the argument, only to make js simpler)
        error (str): An error message if something went wrong.

    """
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    subgraph_name = request.json.get('name')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not subgraph_name or subgraph_name.isspace():
        return jsonify(error='{} name cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    db = get_db()
    db_cursor = db.cursor()

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id, user_id))

    db_cursor.execute('UPDATE subgraph SET name = ? WHERE id = ?',
                      (subgraph_name, subgraph_id))

    db.commit()
    return jsonify(name=subgraph_name)
Beispiel #9
0
def add_value():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    property_uri = request.json.get('property_uri')
    entity_uri = request.json.get('entity_uri')

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not entity_uri or property_uri.isspace():
        return jsonify(error='Entity URI cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    field = subgraph_knowledge.get_field(entity_uri, property_uri)

    if field.is_described:
        return jsonify(
            error='You have to use {} to add a described individual'.format(
                url_for('knowledge.add_entity')))
    if field.is_functional and field.values:
        return jsonify(
            error='You cannot add more than one value to this field.')

    index = subgraph_knowledge.new_value(entity_uri, property_uri)

    if field.options is None:
        render_value_div = get_template_attribute('tool/edit_macros.html',
                                                  'value_free')
    else:
        render_value_div = get_template_attribute('tool/edit_macros.html',
                                                  'value_options')
    value_div = render_value_div(field, '', index)

    return jsonify(value_div=value_div)
Beispiel #10
0
def download_rdf(subgraph_id):
    user_id = g.user['id']

    if not subgraph_id:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id, user_id))

    filename = '{}_{}_{}.ttl'.format(
        current_app.config['FRONTEND_CONFIG']['Subgraph_term'], subgraph_id,
        strftime('%Y-%m-%d-%H-%M-%S'))
    content = get_subgraph_knowledge(subgraph_id).get_serialization(clean=True)

    return Response(
        content,
        mimetype='text/plain',
        headers={'Content-disposition': 'attachment; filename=' + filename})
Beispiel #11
0
def set_finished():
    """Changes the finished flag of a subgraph.
    
    Request args:
        subgraph_id (int): Id of the Subgraph to change.
        finished (str: 'true' or 'false'): The new value of the finished flag of the subgraph.

    Context:
        g.user (sqlite3.Row): Logged in user. Must have access to the subgraph.

    Returns JSON:
        error (str): An error message if something went wrong.

    """
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    finished = request.json.get('finished')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if finished is None:
        return jsonify(error='Argument "finished" cannot be empty.')

    db = get_db()

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id, user_id))

    db.execute('UPDATE subgraph SET finished = ? WHERE id = ?',
               (finished, subgraph_id))
    db.commit()
    return jsonify()
Beispiel #12
0
def add_entity():
    user_id = g.user['id']
    subgraph_id = request.json.get('subgraph_id')
    property_uri = request.json.get('property_uri')
    parent_uri = request.json.get('entity_uri')
    entity_label = request.json.get('label')

    if subgraph_id is None:
        return jsonify(error='{} id cannot be empty.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not parent_uri or parent_uri.isspace():
        return jsonify(error='Parent URI cannot be empty.')
    if not entity_label or entity_label.isspace():
        return jsonify(error='Entity label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    ontology = get_ontology()
    field_is_deletable = ontology.is_property_deletable(property_uri)
    field_is_functional = ontology.is_property_functional(property_uri)
    field_values = subgraph_knowledge.get_property_values(
        parent_uri, property_uri)
    field_range = ontology.get_property_range(property_uri)

    if not field_is_deletable:
        return jsonify(
            error='You are not allowed to add entities to this field.')

    if field_is_functional and field_values:
        return jsonify(
            error='You cannot add more than one value to this field.')

    index = subgraph_knowledge.new_value(parent_uri, property_uri)
    entity, option_fields = subgraph_knowledge.new_individual(
        field_range, entity_label, True)
    subgraph_knowledge.change_value(parent_uri, property_uri, index,
                                    entity.uri)

    render_entity_div = get_template_attribute('tool/edit_macros.html',
                                               'entity_div')
    entity_div = render_entity_div(entity,
                                   index=index,
                                   is_deletable=field_is_deletable,
                                   collapsed=False)

    if option_fields:
        option_fields = [str(f.property_uri) for f in option_fields]
        render_option_div = get_template_attribute('tool/edit_macros.html',
                                                   'option_div')
        option_div = render_option_div(entity, True)
        return jsonify(entity_div=entity_div,
                       remove_plus=field_is_functional,
                       option_fields=option_fields,
                       option_div=option_div)

    return jsonify(entity_div=entity_div, remove_plus=field_is_functional)
Beispiel #13
0
def add_option():
    # If an index is given, the corresponding value is changed to the new option
    user_id = g.user['id']
    user_uri = g.user['uri']
    subgraph_id = request.json.get('subgraph_id')
    entity_uri = request.json.get('entity_uri')
    property_uri = request.json.get('property_uri')
    label = request.json.get('label')
    index = request.json.get('index')

    if subgraph_id is None:
        return jsonify(error='Subgraph id cannot be empty.')
    try:
        subgraph_id = int(subgraph_id)
    except ValueError:
        return jsonify(error='{} id has to be an integer.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term']))
    if not property_uri or property_uri.isspace():
        return jsonify(error='Property URI cannot be empty.')
    if not label or label.isspace():
        return jsonify(error='Label cannot be empty.')

    if not subgraph_access(user_id, subgraph_id):
        return jsonify(error=MSG_SUBGRAPH_ACCESS.format(subgraph_id, user_id))

    subgraph_knowledge = get_subgraph_knowledge(subgraph_id)
    ontology = get_ontology()

    if ontology.is_property_described(property_uri):
        return jsonify(
            error='Use _add_entity to add entities to a described field.')
    if not ontology.is_property_add_custom_option_allowed(property_uri):
        return jsonify(error='Adding options to this field is not allowed.')

    option, option_fields = ontology.new_option(
        ontology.get_property_range(property_uri), label, user_uri)

    if index is not None:
        try:
            index = int(index)
        except ValueError:
            return jsonify(error='Index has to be an integer.')
        # not only add the option to the ontology but also to the list of values of the field
        if not entity_uri or entity_uri.isspace():
            return jsonify(error='Entity URI cannot be empty.')

        if index == subgraph_knowledge.get_property_free_index(
                entity_uri, property_uri):
            index = subgraph_knowledge.new_value(entity_uri, property_uri)
        subgraph_knowledge.change_value(entity_uri, property_uri, index,
                                        option.uri)

    render_option_div = get_template_attribute('tool/edit_macros.html',
                                               'option_div')
    option_div = render_option_div(option, True)

    return jsonify(option_div=option_div,
                   option_fields=list(option_fields),
                   option_label=option.label,
                   option_uri=option.uri,
                   index=index)