示例#1
0
def test_get_close_db(app):
    with app.app_context():
        db = get_db()
        assert db is get_db()

    with pytest.raises(ProgrammingError) as e:
        db.execute('SELECT 1')

    assert 'closed' in str(e.value)
示例#2
0
    def get_new_uri(self, class_uri, subgraph_id=None, base=None):
        # construct a unique uri
        if type(class_uri) == str:
            class_uri = URIRef(class_uri)
        if base is None:
            base = self.get_base()

        db = get_db()
        used_uris = {
            str(parse_n3_term(row['subject']))
            for row in db.execute(
                'SELECT DISTINCT subject FROM knowledge').fetchall()
        }
        used_uris.update({
            str(parse_n3_term(row['subject']))
            for row in db.execute(
                'SELECT DISTINCT subject FROM ontology').fetchall()
        })
        used_uris.update({
            str(parse_n3_term(row['uri']))
            for row in db.execute('SELECT DISTINCT uri FROM user').fetchall()
        })

        uri = str(base) + get_uri_suffix(class_uri) + '_'
        if subgraph_id:
            uri += str(subgraph_id) + '_'
        return URIRef(
            next(uri + str(i) for i in count(1)
                 if uri + str(i) not in used_uris))
示例#3
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))
示例#4
0
def edit_user():
    user_id = request.json.get('user_id')
    user_name = request.json.get('name')
    user_password = request.json.get('password')
    user_is_admin = request.json.get('admin') is not None

    if user_id is None:
        return jsonify(error='User id cannot be empty.')
    try:
        user_id = int(user_id)
    except ValueError:
        return jsonify(error='User id has to be an integer.')
    if user_id == g.user['id'] and not user_is_admin:
        return jsonify(
            error='You cannot remove admin rights from your own account.')
    if not user_name or user_name.isspace():
        return jsonify(error='User name cannot be empty.')

    db = get_db()

    db.execute('UPDATE user SET username = ?, admin = ? WHERE id = ?',
               (user_name, user_is_admin, user_id))

    if user_password is not None and not user_password.isspace():
        db.execute('UPDATE user SET password = ? WHERE id = ?',
                   (generate_password_hash(user_password), user_id))

    db.commit()
    return jsonify(user_name=user_name, user_is_admin=user_is_admin)
示例#5
0
    def __init__(self, subgraph_id):
        super().__init__(Graph())
        self.id = subgraph_id
        # since rdf triples are not ordered but the values of the property fields in the tool are we need to store this
        # additional information outside the rdf graph object:
        self.properties = defaultdict(
            dict
        )  # includes deleted! (There has to be a better name for this?)
        self.root = None

        db = get_db()

        for row in db.execute('SELECT * FROM namespace').fetchall():
            self.graph.namespace_manager.bind(row['prefix'],
                                              parse_n3_term(row['uri']))

        for row in db.execute(
                'SELECT subject, predicate, object, property_index, deleted FROM knowledge WHERE subgraph_id = ?',
            (subgraph_id, )).fetchall():
            subject, predicate, object_ = row_to_rdf(row)
            index = row['property_index']
            deleted = row['deleted']
            if deleted is None and str(object_) != '':
                self.graph.add((subject, predicate, object_))
            if index is not None:
                self.properties[(subject, predicate)][index] = object_
示例#6
0
    def delete_individual_recursive(self, uri):
        if type(uri) == str:
            uri = URIRef(uri)

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

        stack = [uri]
        deleted = []
        while stack:
            u = stack.pop()
            deleted.append(str(u))
            stack += self.get_individual_children(u)

            # remove links from parents
            self.graph.remove((None, None, u))
            db_cursor.execute(
                'UPDATE knowledge SET deleted = ? WHERE subgraph_id = ? AND object = ? AND deleted IS NULL',
                (uri.n3(), self.id, u.n3()))

            # remove links to children
            self.graph.remove((u, None, None))
            db_cursor.execute(
                'UPDATE knowledge SET deleted = ? WHERE subgraph_id = ? AND subject = ? AND deleted IS NULL',
                (uri.n3(), self.id, u.n3()))
        db.commit()

        self.root = None  # forces a rebuild of the root entity

        return deleted
示例#7
0
    def load_rdf_data(self, data, rdf_format='turtle'):
        super().load_rdf_data(data, rdf_format)

        self.properties = defaultdict(dict)

        db = get_db()
        db.execute('DELETE FROM knowledge WHERE subgraph_id = ?', (self.id, ))
        for subject, predicate, object_ in self.graph[::]:
            index = None
            if (subject, predicate) in self.properties:
                index = max(self.properties[(subject, predicate)].keys()) + 1
                self.properties[(subject, predicate)][index] = object_
            elif predicate in get_ontology().graph[:RDF.type:OWL.ObjectProperty] \
                    or predicate in get_ontology().graph[:RDF.type:OWL.DatatypeProperty]:
                index = 1
                self.properties[(subject, predicate)][index] = object_
            db.execute(
                'INSERT INTO knowledge (subgraph_id, subject, predicate, object, property_index)'
                ' VALUES (?, ?, ?, ?, ?)',
                (self.id, subject.n3(), predicate.n3(), object_.n3(), index))
        db.commit()

        self.root = None  # forces a rebuild of the root entity
        self.get_root(
        )  # to test immediately whether everything is building correctly
示例#8
0
def test_set_finished(client, auth):
    db = get_db()
    assert not db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['finished']
    auth.login()
    response = client.get('/_set_finished?subgraph_id=1&finished=true')
    assert 'error' not in response.get_json()
    assert db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['finished']
示例#9
0
def test_undo_delete_subgraph(client, auth):
    db = get_db()
    assert db.execute('SELECT * FROM subgraph WHERE id = 4').fetchone()['deleted']
    auth.login()
    response = client.get('/_undo_delete_subgraph?subgraph_id=4')
    assert 'error' not in response.get_json()
    assert not db.execute('SELECT * FROM subgraph WHERE id = 4').fetchone()['deleted']
示例#10
0
def get_overview():
    subgraph_id = request.json.get('subgraph_id')

    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']))

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

    if subgraph is None:
        return jsonify(error='{} with id {} does not exist.'.format(
            current_app.config['FRONTEND_CONFIG']['Subgraph_term'],
            subgraph_id))

    if not subgraph['finished']:
        return jsonify(error='You have no access to {} with id {}.'.format(
            current_app.config['FRONTEND_CONFIG']['subgraph_term'],
            subgraph_id))

    render_overview_table = get_template_attribute('tool/overview_table.html',
                                                   'overview')
    overview_table = render_overview_table(
        get_subgraph_knowledge(subgraph_id).get_graph(clean=True,
                                                      ontology=True))

    return jsonify(overview_table=overview_table)
示例#11
0
def read_only_view(subgraph_id):
    """Edit view.
    Displays knowledge about a subgraph and allows users to edit it."""
    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['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)))

    root = get_subgraph_knowledge(subgraph_id).get_root()

    return render_template('tool/edit.html',
                           subgraph=subgraph,
                           root=root,
                           read_only=True)
示例#12
0
def test_edit_subgraph_name(client, auth):
    db = get_db()
    assert db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['name'] == 'Clinical trial 1'
    auth.login()
    response = client.get('/_edit_subgraph_name?subgraph_id=1&name=test')
    assert 'error' not in response.get_json()
    assert response.get_json()['name'] == 'test'
    assert db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['name'] == 'test'
示例#13
0
def test_delete_subgraph(client, auth):
    db = get_db()
    assert not db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['deleted']
    auth.login()
    response = client.get('/_delete_subgraph?subgraph_id=1')
    assert 'error' not in response.get_json()
    assert response.get_json()['name'] == 'Clinical trial 1'
    assert db.execute('SELECT * FROM subgraph WHERE id = 1').fetchone()['deleted']
示例#14
0
def test_add_subgraph(client, auth):
    db = get_db()
    assert not db.execute('SELECT EXISTS (SELECT 1 FROM subgraph WHERE name = "new")').fetchone()[0]
    auth.login()
    response = client.get('/_add_subgraph?name=new')
    assert 'error' not in response.get_json()
    new = db.execute('SELECT * FROM subgraph WHERE name = "new"').fetchone()
    assert new
    assert response.get_json()['redirect'] == url_for('tool.index', subgraph_id=new['id'])
示例#15
0
    def __init__(self):
        super().__init__(Graph())

        db = get_db()
        for row in db.execute('SELECT * FROM ontology').fetchall():
            self.graph.add(row_to_rdf(row))

        for row in db.execute('SELECT * FROM namespace').fetchall():
            self.graph.namespace_manager.bind(row['prefix'],
                                              parse_n3_term(row['uri']))
示例#16
0
def search_view():
    filter_object = get_filter()

    db = get_db()
    rows = db.execute(
        'SELECT id, name FROM access JOIN subgraph ON subgraph_id = id'
        ' WHERE deleted = 0  AND finished = 1').fetchall()

    return render_template('tool/search.html',
                           filter=filter_object,
                           subgraphs=rows)
示例#17
0
def user_administration(user_id):

    db = get_db()
    user = db.execute('SELECT * FROM user WHERE id = ?',
                      (user_id, )).fetchone()

    subgraph_list = db.execute(
        'SELECT id, name, finished'
        ' FROM access JOIN subgraph ON subgraph_id = id'
        ' WHERE user_id = ? and deleted = 0'
        ' ORDER BY subgraph_id ASC', (user_id, )).fetchall()

    return render_template('tool/admin_user.html',
                           user=user,
                           subgraph_list=subgraph_list)
示例#18
0
def undo_delete_user():
    user_id = request.json.get('user_id')

    if user_id is None:
        return jsonify(error='User id cannot be empty.')
    try:
        user_id = int(user_id)
    except ValueError:
        return jsonify(error='User id has to be an integer.')

    db = get_db()
    db.execute('UPDATE user SET deleted = 0 WHERE id = ?', (user_id, ))
    db.commit()

    return jsonify()
示例#19
0
    def change_label(self, entity_uri, label):
        entity_uri = URIRef(entity_uri)

        label = Literal(label)

        self.graph.remove((entity_uri, RDFS.label, None))
        self.graph.add((entity_uri, RDFS.label, label))

        db = get_db()
        db.execute(
            'UPDATE knowledge SET object = ? '
            '   WHERE subgraph_id = ? AND subject = ? AND predicate = ?',
            (label.n3(), self.id, entity_uri.n3(), RDFS.label.n3()))
        db.commit()

        self.root = None  # forces a rebuild of the root entity
示例#20
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)
示例#21
0
def index(message=None):
    if message:
        message = unquote(message)

    db = get_db()
    user_list = db.execute(
        'SELECT id, username, admin, uri'
        ' FROM user'
        ' WHERE deleted = 0'
        ' ORDER BY id ASC', ).fetchall()

    show_admin_message, admin_message = get_admin_message()

    return render_template('tool/admin.html',
                           user_list=user_list,
                           show_admin_message=show_admin_message,
                           admin_message=admin_message,
                           message=message)
示例#22
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)
示例#23
0
def undo_delete_subgraph():
    """Marks a subgraph as not deleted.

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

    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')

    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()

    access = db_cursor.execute(
        'SELECT EXISTS ('
        ' SELECT 1 FROM access JOIN subgraph ON subgraph_id = id WHERE user_id = ? AND subgraph_id = ?'
        ')', (user_id, subgraph_id)).fetchone()[0]

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

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

    db.commit()

    return jsonify()
示例#24
0
    def load_rdf_data(self, data, rdf_format='turtle'):
        super().load_rdf_data(data, rdf_format)

        # todo check if the graph works: build root and all possible children?
        #  check property orders: [f.order for f in fields] != list(range(1, len(fields) + 1))

        db = get_db()
        db.execute('DELETE FROM ontology')

        for subject, predicate, object_ in self.graph[::]:
            db.execute(
                'INSERT INTO ontology (subject, predicate, object) VALUES (?, ?, ?)',
                (subject.n3(), predicate.n3(), object_.n3()))

        for prefix, uri in self.graph.namespaces():
            db.execute('INSERT INTO namespace (prefix, uri) VALUES (?, ?)',
                       (prefix, uri.n3()))

        db.commit()
示例#25
0
    def undo_delete_individual(self, uri):
        if type(uri) == str:
            uri = URIRef(uri)

        db = get_db()

        rows = db.execute(
            'SELECT subject, predicate, object FROM knowledge WHERE subgraph_id = ? AND deleted = ?',
            (self.id, uri.n3())).fetchall()

        for row in rows:
            self.graph.add(row_to_rdf(row))

        db.execute(
            'UPDATE knowledge SET deleted = NULL WHERE subgraph_id = ? AND deleted = ?',
            (self.id, uri.n3()))

        db.commit()

        self.root = None  # forces a rebuild of the root entity
示例#26
0
    def new_value(self, entity_uri, property_uri):
        if type(entity_uri) == str:
            entity_uri = URIRef(entity_uri)
        if type(property_uri) == str:
            property_uri = URIRef(property_uri)

        index = self.get_property_free_index(entity_uri, property_uri)
        value = Literal('')

        self.graph.add((entity_uri, property_uri, value))
        self.properties[(entity_uri, property_uri)][index] = value
        db = get_db()
        db.execute(
            'INSERT INTO knowledge (subgraph_id, subject, predicate, object, property_index) VALUES (?, ?, ?, ?, ?)',
            (self.id, entity_uri.n3(), property_uri.n3(), value.n3(), index))
        db.commit()

        self.root = None  # forces a rebuild of the root entity

        return index
示例#27
0
def search():
    filter_data = request.json

    # todo get_result(filter_data) should be a method of the filter
    # get list of subgraphs that are finished and not deleted
    db = get_db()
    rows = db.execute('SELECT id FROM access JOIN subgraph ON subgraph_id = id'
                      ' WHERE deleted = 0 AND finished = 1').fetchall()
    results = {row['id'] for row in rows}
    knowledge = {
        subgraph_id:
        {(str(p), str(o))
         for s, p, o in get_subgraph_knowledge(subgraph_id).get_graph(
             clean=True)}
        for subgraph_id in results
    }
    results = filter(
        lambda subgraph_id: all(po in knowledge[subgraph_id]
                                for po in filter_data.items()), results)

    return jsonify(results=[str(subgraph_id) for subgraph_id in results])
示例#28
0
def index(message=None):
    """Home view of the tool.
    Contains list of accessible subgraphs.
    """
    user_id = g.user['id']

    if message:
        message = unquote(message)

    db = get_db()

    # for the subgraph menu
    subgraph_list = db.execute(
        'SELECT id, name, finished'
        ' FROM access JOIN subgraph ON subgraph_id = id'
        ' WHERE user_id = ? and deleted = 0'
        ' ORDER BY subgraph_id ASC', (user_id, )).fetchall()

    return render_template('tool/index.html',
                           subgraph_list=subgraph_list,
                           message=message)
示例#29
0
    def change_value(self, entity_uri, property_uri, index, value):
        if type(entity_uri) == str:
            entity_uri = URIRef(entity_uri)
        if type(property_uri) == str:
            property_uri = URIRef(property_uri)

        db = get_db()

        # delete previous value from graph
        prev_value = db.execute(
            'SELECT object FROM knowledge '
            '   WHERE subgraph_id = ? AND subject = ? AND predicate = ? AND property_index = ?',
            (self.id, entity_uri.n3(), property_uri.n3(), index)).fetchone()
        if prev_value:
            self.graph.remove((entity_uri, property_uri,
                               parse_n3_term(prev_value['object'])))

        # add new value to graph
        validity, value = self.check_property_value(property_uri, value)
        if validity:
            # the check returned an error message
            del self.properties[(entity_uri, property_uri)][index]
            db.execute(
                'UPDATE knowledge SET object = ? '
                '   WHERE subgraph_id = ? AND subject = ? AND predicate = ? AND property_index = ?',
                (Literal('').n3(), self.id, entity_uri.n3(), property_uri.n3(),
                 index))
            db.commit()
            self.root = None
            return validity

        self.graph.add((entity_uri, property_uri, value))
        self.properties[(entity_uri, property_uri)][index] = value
        db.execute(
            'UPDATE knowledge SET object = ? '
            '   WHERE subgraph_id = ? AND subject = ? AND predicate = ? AND property_index = ?',
            (value.n3(), self.id, entity_uri.n3(), property_uri.n3(), index))
        db.commit()

        self.root = None  # forces a rebuild of the root entity
示例#30
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()