示例#1
0
def get_user(username: str):
    query = f'MATCH (a) WHERE a.username = \'{username}\' RETURN a'

    with neo4j_driver.session() as session:
        user_in_db = session.run(query)
        user_data = user_in_db.data()[0]['a']
        return UserInDB(**user_data)
示例#2
0
async def create_user(username: str, password: str, 
                      full_name: Optional[str] = None,
                      disabled: Optional[bool] = None):

    # Create dictionary of new user attributes
    attributes = {'username':username,
                  'full_name':full_name,
                  'hashed_password':create_password_hash(password),
                  'joined':str(datetime.utcnow()),
                  'disabled':disabled}

    # Write Cypher query and run against the database
    cypher_search = 'MATCH (user:User) WHERE user.username = $username RETURN user'
    cypher_create = 'CREATE (user:User {params}) RETURN user'

    with neo4j_driver.session() as session:
        # First, run a search of users to determine if username is already in use
        check_users = session.run(query=cypher_search, parameters={'username':username})
        
        # Return error message if username is already in the database
        if check_users.data():
            raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=f"Operation not permitted, user with username {username} already exists.",
            headers={"WWW-Authenticate": "Bearer"})

        response = session.run(query=cypher_create, parameters={'params':attributes})
        user_data = response.data()[0]['user']
    user = User(**user_data)
    return user
示例#3
0
async def read_node_id(node_id: int,
                       current_user: User = Depends(get_current_active_user)):
    '''
    **Retrieves data about a node in the graph, based on node ID.**

    :param **node_id** (str) - node id, used for indexed search

    :returns: Node response, with node id, labels, and properties.
    '''

    cypher = '''Match (node)
                WHERE ID(node) = $node_id
                RETURN ID(node) as id, LABELS(node) as labels, node'''

    with neo4j_driver.session() as session:
        result = session.run(query=cypher, parameters={'node_id': node_id})

        node_data = result.data()[0]

    # Check node for type User, and send error message if needed
    if 'User' in node_data['labels']:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=
            f"Operation not permitted, please use User endpoints to retrieve user information.",
            headers={"WWW-Authenticate": "Bearer"})

    # Return Node response
    return Node(node_id=node_data['id'],
                labels=node_data['labels'],
                properties=node_data['node'])
示例#4
0
async def update_relationship(relationship_id: int, attributes: dict):

    cypher = '''MATCH (nodeA)-[relationship]->(nodeB) 
                WHERE ID(relationship) = $rel_id
                SET relationship += $attributes
                RETURN nodeA, ID(nodeA), LABELS(nodeA), relationship, ID(relationship), TYPE(relationship), nodeB, ID(nodeB), LABELS(nodeB)'''

    with neo4j_driver.session() as session:
        result = session.run(query=cypher,
                             parameters={
                                 'rel_id': relationship_id,
                                 'attributes': attributes
                             })

        relationship_data = result.data()

    # Organise the data about the nodes in the relationship
    source_node = Node(node_id=relationship_data['ID(nodeA)'],
                       labels=relationship_data['LABELS(nodeA)'],
                       properties=relationship_data['nodeA'])

    target_node = Node(node_id=relationship_data['ID(nodeB)'],
                       labels=relationship_data['LABELS(nodeB)'],
                       properties=relationship_data['nodeB'])

    # Return Relationship response
    return Relationship(
        relationship_id=relationship_data['ID(relationship)'],
        relationship_type=relationship_data['TYPE(relationship)'],
        properties=relationship_data['PROPERTIES(relationship)'],
        source_node=source_node,
        target_node=target_node)
示例#5
0
async def update_node(node_id: int, attributes: dict):
    # Check that property to update is not part of base list
    for key in attributes:
        if key in base_properties:
            raise HTTPException(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                detail=
                f"Operation not permitted, that property field cannot be updated.",
                headers={"WWW-Authenticate": "Bearer"})

    cypher = '''MATCH (node) WHERE ID(node) = $id
                SET node += $attributes
                RETURN node, ID(node) as id, LABELS(node) as labels'''

    with neo4j_driver.session() as session:
        result = session.run(query=cypher,
                             parameters={
                                 'id': node_id,
                                 'attributes': attributes
                             })

        node_data = result.data()[0]

    # Return Node response
    return Node(node_id=node_data['id'],
                labels=node_data['labels'],
                properties=node_data['node'])
示例#6
0
async def read_nodes(search_node_property: str,
                     node_property_value: str,
                     current_user: User = Depends(get_current_active_user)):
    '''
    Retrieves data about a collection of nodes in the graph, based on node property.

    :param **node_property** (str) - property to search in nodes

    :param **node_property_value** (str) - value of property, to select the correct node

    :returns: Node response, with node id, labels, and properties. Returns only first response.
    '''

    cypher = (
        f'Match (node)\n'
        f'WHERE node.{search_node_property} = \'{node_property_value}\'\n'
        'RETURN ID(node) as id, LABELS(node) as labels, node')

    with neo4j_driver.session() as session:
        result = session.run(query=cypher)

        collection_data = result.data()

    node_list = []
    for node in collection_data:
        # Create node for each result in query
        node = Node(node_id=node['id'],
                    labels=node['labels'],
                    properties=node['node'])

        # Append each node result into Nodes list
        node_list.append(node)

    # Return Nodes response with collection as list
    return Nodes(nodes=node_list)
示例#7
0
async def read_user(username: str):
    query = 'MATCH (user) WHERE user.username = $username RETURN user'

    with neo4j_driver.session() as session:
        user_in_db = session.run(query=query, parameters={'username':username})
        user_data = user_in_db.data()[0]['user']
    
    user_id = user_data['id']

    return User(**user_data)
示例#8
0
async def create_node(label: str,
                      node_attributes: dict,
                      permission: Optional[str] = None,
                      current_user: User = Depends(get_current_active_user)):
    # Check that node is not User
    if label == 'User':
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=
            f"Operation not permitted, cannot create a User with this method.",
            headers={"WWW-Authenticate": "Bearer"})

    # Check that node has an acceptable label
    if label not in node_labels:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=f"Operation not permitted, node label is not accepted.",
            headers={"WWW-Authenticate": "Bearer"})

    # Check that attributes dictionary does not modify base fields
    for key in node_attributes:
        if key in base_properties:
            raise HTTPException(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                detail=
                f"Operation not permitted, you cannot modify those fields with this method.",
                headers={"WWW-Authenticate": "Bearer"})

    cypher = (
        f'CREATE (new_node:{label})\n'
        'SET new_node.created_by = $created_by\n'
        'SET new_node.created_time = $created_time\n'
        'SET new_node.permission = $permission\n'
        'SET new_node += {attributes}\n'
        'RETURN new_node, LABELS(new_node) as labels, ID(new_node) as id')

    with neo4j_driver.session() as session:
        result = session.run(query=cypher,
                             parameters={
                                 'created_by': current_user.username,
                                 'created_time': str(datetime.utcnow()),
                                 'permission': permission,
                                 'attributes': node_attributes
                             })

        node_data = result.data()[0]

    return Node(node_id=node_data['id'],
                labels=node_data['labels'],
                properties=node_data['new_node'])
示例#9
0
async def reset_password(new_password: str, current_user: User = Depends(get_current_active_user)):
    # Get current user's username and encrypt new password
    username = current_user.username
    new_password_hash = create_password_hash(new_password)

    # Execute Cypher query to reset the hashed_password attribute
    cypher_reset_password = ('MATCH (user) WHERE user.username = $username\n'
                             'SET user.hashed_password = $new_password_hash\n'
                             'RETURN user')
    
    with neo4j_driver.session() as session:
        updated_user = session.run(query=cypher_reset_password, 
                                   parameters={'username':username,
                                               'new_password_hash':new_password_hash})
        user_data = updated_user.data()[0]['user']
    user = User(**user_data)
    return user
示例#10
0
async def delete_node(node_id: int):

    cypher = '''MATCH (node)
                WHERE ID(node) = $node_id
                DELETE node'''

    with neo4j_driver.session() as session:
        result = session.run(query=cypher, parameters={'node_id': node_id})

        node_data = result.data()

    # Confirm deletion was completed by empty response
    if not node_data:
        return {
            'response':
            f'Node with ID: {node_id} was successfully deleted from the graph.'
        }

    else:
        return node_data
示例#11
0
async def update_user(attributes: dict, username: str):
    # Add check to stop call if password is being changed
    for k in attributes:
        if k == 'hashed_password':
            raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail="Operation not permitted, cannot update password with this method.",
            headers={"WWW-Authenticate": "Bearer"})
    
    # Execute Cypher query to reset the hashed_password attribute
    cypher_update_user = ('MATCH (user: User) WHERE user.username = $user\n'
                          'SET user += {dict_params}\n'
                          'RETURN user')

    with neo4j_driver.session() as session:
        updated_user = session.run(query=cypher_update_user,
                                   parameters={'user':username, 'dict_params':attributes})
        user_data = updated_user.data()[0]['user']
    
    user = User(**user_data)
    return user
示例#12
0
async def delete_relationship(relationship_id: int):

    cypher = '''MATCH (a)-[relationship]->(b)
                WHERE ID(relationship) = $relationship_id
                DELETE relationship'''

    with neo4j_driver.session() as session:
        result = session.run(query=cypher,
                             parameters={'relationship_id': relationship_id})

        relationship_data = result.data()

    # Confirm deletion was completed by empty response
    if not relationship_data:
        return {
            'response':
            f'Relationship with ID: {relationship_id} was successfully deleted from the graph.'
        }

    else:
        return relationship_data
示例#13
0
async def cypher_query(cypher_string: str):
    with neo4j_driver.session() as session:
        response = session.run(query=cypher_string)
        query_response = Query(response=response.data())
        return query_response
示例#14
0
async def create_relationship(
    source_node_label: str,
    source_node_property: str,
    source_node_property_value: str,
    target_node_label: str,
    target_node_property: str,
    target_node_property_value: str,
    relationship_type: str,
    relationship_attributes: dict,
    permission: Optional[str] = None,
    current_user: User = Depends(get_current_active_user)):
    # Check that relationship has an acceptable type
    if relationship_type not in relationship_types:
        raise HTTPException(
            status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
            detail=
            f"Operation not permitted, relationship type is not accepted.",
            headers={"WWW-Authenticate": "Bearer"})

    # Check that attributes dictionary does not modify base fields
    for key in relationship_attributes:
        if key in base_properties:
            raise HTTPException(
                status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
                detail=
                f"Operation not permitted, you cannot modify those fields with this method.",
                headers={"WWW-Authenticate": "Bearer"})

    cypher = (
        f'MATCH (nodeA:{source_node_label}) WHERE nodeA.{source_node_property} = $nodeA_property\n'
        f'MATCH (nodeB:{target_node_label}) WHERE nodeB.{target_node_property} = $nodeB_property\n'
        f'CREATE (nodeA)-[relationship:{relationship_type}]->(nodeB)\n'
        'SET relationship.created_by = $created_by\n'
        'SET relationship.created_time = $created_time\n'
        'SET relationship.permission = $permission\n'
        'SET relationship += {relationship_attributes}\n'
        'RETURN nodeA, nodeB, LABELS(nodeA), LABELS(nodeB), ID(nodeA), ID(nodeB), ID(relationship), TYPE(relationship), PROPERTIES(relationship)'
    )

    with neo4j_driver.session() as session:
        result = session.run(query=cypher,
                             parameters={
                                 'created_by': current_user.username,
                                 'created_time': str(datetime.utcnow()),
                                 'permission': permission,
                                 'nodeA_property': source_node_property_value,
                                 'nodeB_property': target_node_property_value,
                                 'relationship_attributes':
                                 relationship_attributes
                             })

        relationship_data = result.data()[0]

    # Organise the data about the nodes in the relationship
    source_node = Node(node_id=relationship_data['ID(nodeA)'],
                       labels=relationship_data['LABELS(nodeA)'],
                       properties=relationship_data['nodeA'])

    target_node = Node(node_id=relationship_data['ID(nodeB)'],
                       labels=relationship_data['LABELS(nodeB)'],
                       properties=relationship_data['nodeB'])

    # Return Relationship response
    return Relationship(
        relationship_id=relationship_data['ID(relationship)'],
        relationship_type=relationship_data['TYPE(relationship)'],
        properties=relationship_data['PROPERTIES(relationship)'],
        source_node=source_node,
        target_node=target_node)