示例#1
0
    def custom_validation(cls,
                          data,
                          outv_id=None,
                          inv_id=None,
                          outv_label=None,
                          inv_label=None):
        """ Provides validation to confirm that
            1) A coreVertex is only ever owned by one team/coreVertex at a time
            2) A coreVertex can only be owned by a coreVertex whose Template
                 has the canHaveChildren property set to True
        """
        existing_edge_q = f"g.V().has('{inv_label}', 'id', '{inv_id}')" + \
            f".inE('owns')"
        existing_edge = client.submit(existing_edge_q).all().result()
        if existing_edge:
            raise CustomValidationFailedException(
                "CoreVertex can only be owned by a single parent at a time!")

        # Checking for the template's canHaveChildren property if the
        # parent is a coreVertex
        if outv_label == "coreVertex":
            parent_template_query = \
                f"g.V().has('{outv_label}', 'id', '{outv_id}')" + \
                f".out('{CoreVertexInheritsFromTemplate.LABEL}')"
            parent_template = Template.vertex_to_instance(
                client.submit(parent_template_query).all().result()[0])
            if parent_template.canHaveChildren != "True":
                raise CustomValidationFailedException(
                    "CoreVertex can only be owned by a CoreVertex that has"
                    " it's template's canHaveChildren property set to `true`!")

        return data
示例#2
0
    def get_team_owner(self, team_id):
        """ Returns the Account instance that owns the given team """
        query = f"g.V().hasLabel('{core.Team.LABEL}').has('id', '{team_id}')" + \
            f".in('{AccountOwnsTeam.LABEL}')"

        owner = client.submit(query).all().result()
        return Account.vertex_to_instance(owner[0])
示例#3
0
    def all_team_templates(cls, team_id):
        """ Return all templates under the given team """
        query = f"g.V().has('{Team.LABEL}', 'id', '{team_id}')" + \
            f".out('{cls.LABEL}')"
        results = client.submit(query).all().result()

        return [Template.vertex_to_instance(i) for i in results]
示例#4
0
    def get_templates_with_details(cls, team_id):
        """ Returns the all Template instance owned by the given team
            with the required details;
                - id, name, topicsCount
            -- SERIALIZED
        """
        query = f"g.V().has('{Team.LABEL}', 'id', '{team_id}')" + \
            f".out('{TeamOwnsTemplate.LABEL}').hasLabel('{Template.LABEL}')" + \
            f".project('id', 'name', 'topicsCount', 'properties')" + \
            f".by(values('id')).by(values('name'))" + \
            f".by(inE('{CoreVertexInheritsFromTemplate.LABEL}').outV()" + \
            f".hasLabel('{CoreVertex.LABEL}').count())" + \
            f".by(outE('{TemplateHasProperty.LABEL}').inV().fold())"
        result = client.submit(query).all().result()

        templates = []
        for template in result:
            properties = [
                TemplateProperty.vertex_to_instance(i)
                for i in template["properties"]
            ]
            template["properties"] = []
            for prop in properties:
                template["properties"].append({
                    "id": prop.id,
                    "name": prop.name,
                    "fieldType": prop.fieldType,
                    "propertyOptions": prop.propertyOptions,
                    "index": prop.index
                })
            templates.append(template)

        return templates
示例#5
0
    def get_user_permissions(self, user_id):
        """ Returns all roles assigned to the given user for this CoreVertex
            as a dictionary of
            {direct_role: <edge>, indirect_roles: [edges...]}
        """
        # This will return all of the permissions the user has for all of the
        # vertices in this vertex's path to the root
        query = f"g.V().has('{self.LABEL}', 'id', '{self.id}')" + \
            f".until(__.hasLabel('{Team.LABEL}'))" + \
            f".repeat(__.in('{CoreVertexOwnership.LABEL}')).path()" + \
            f".unfold().inE('{auth.UserAssignedToCoreVertex.LABEL}')" + \
            f".as('e').outV().has('{auth.User.LABEL}', 'id', '{user_id}')" + \
            f".select('e')"
        results = client.submit(query).all().result()

        roles = {"indirect_roles": [], "direct_role": None}

        for edge in results:
            if edge["inV"] == self.id:
                roles["direct_role"] = auth.UserAssignedToCoreVertex \
                    .edge_to_instance(edge).role
            else:
                roles["indirect_roles"].append(
                    auth.UserAssignedToCoreVertex.edge_to_instance(edge).role)

        return roles
示例#6
0
    def get_template(cls, vertex_type, vertex_id, template_id):
        """ Returns the template owned by the given:
                "Team" if the vertex_type is a `team`, or
                "CoreVertex's Root Level Team" if the vertex_type is a
                    `coreVertex`
        """
        base_template_query = f".out('{TeamOwnsTemplate.LABEL}')" + \
            f".has('id', '{template_id}')"

        if vertex_type == "team":
            # If this node is the team (root), we can just check if it has an
            # outgoing edge to this template
            query = f"g.V().has('{Team.LABEL}', 'id', '{vertex_id}')" + \
                base_template_query
        else:
            # Otherwise, we have to find the Team (Root) for this CoreVertex,
            # and then check if that team has the template
            query = f"g.V().has('{CoreVertex.LABEL}', 'id', '{vertex_id}')" + \
                f".repeat(__.in('{CoreVertexOwnership.LABEL}'))" + \
                f".until(__.hasLabel('{Team.LABEL}'))" + \
                base_template_query

        template = client.submit(query).all().result()
        if not template:
            return None
        return Template.vertex_to_instance(template[0])
示例#7
0
    def get_template_with_properties(cls, template_id, parent_team_id=None):
        """ Returns the template and the template properties belonging to it
            in a single query
        """
        query = "g.V()"
        # Prepending a team query if the team id arg is provided
        if parent_team_id:
            query += f".has('{Team.LABEL}', 'id', " + \
                f"'{parent_team_id}').out('{TeamOwnsTemplate.LABEL}')"
        query += f".has('{Template.LABEL}', 'id', '{template_id}')" + \
            f".fold().project('template', 'properties').by(unfold())" + \
            f".by(unfold().out('{TemplateHasProperty.LABEL}').fold())"

        try:
            # This raises a 597 error if there's nothing found
            res = client.submit(query).all().result()
        except:
            return None

        template = Template.vertex_to_instance(res[0]["template"])
        template.properties = [
            TemplateProperty.vertex_to_instance(i)
            for i in res[0]["properties"]
        ]

        return template
示例#8
0
    def list_messages(node_id,
                      start=0,
                      end=10,
                      date_filter="gt",
                      filter_date=None):
        """ Returns all messages sent against the given node since the
            given `since` datetime object
            NOTE: Serialized
        """
        query = f"g.V().has('id', '{node_id}')" + \
            f".out('{NodeHasMessage.LABEL}').order().by('sent_at')"

        if date_filter and filter_date:
            query += f".has('sent_at', {date_filter}('{filter_date.isoformat()}'))"

        query += f".project('id', 'text', 'sent_at', 'author')" + \
            f".by(values('id'))" + \
            f".by(values('text'))" +\
            f".by(values('sent_at'))" + \
            f".by(inE('{UserSentMessage.LABEL}').outV())"

        result = client.submit(query).all().result()
        if result:
            result = result[start:end]
            messages = []

            for item in result:
                msg = Message(id=item["id"],
                              text=item["text"],
                              sent_at=item["sent_at"])
                msg.author = auth.User.vertex_to_instance(item["author"])
                messages.append(msg)
            return messages
        return result
示例#9
0
    def get_teams(cls, account_id):
        """ Returns all teams owned by this account id """
        query = f"g.V().hasLabel('{Account.LABEL}')" + \
            f".has('id', '{account_id}').out('{cls.LABEL}')"
        results = client.submit(query).all().result()

        return [core.Team.vertex_to_instance(i) for i in results]
示例#10
0
    def get_favorite_nodes(cls, user_id, parent_id=None):
        """ Returns all of the favorite nodes for the given user that
            he has access to
        """
        if parent_id:
            query = f"g.V().has('id', '{parent_id}')" + \
                f".emit()" + \
                f".until(out('{CoreVertexOwnership.LABEL}').count().is(0))" + \
                f".repeat(out('{CoreVertexOwnership.LABEL}'))"
        else:
            query = f"g.V().hasLabel('{CoreVertex.LABEL}')"

        query += f".as('cv').in('{cls.LABEL}').has('id', '{user_id}')" + \
            f".select('cv')"

        result = client.submit(query).all().result()

        nodes = []
        for node in result:
            if node["label"] == "coreVertex":
                nodes.append(CoreVertex.vertex_to_instance(node))
            else:
                nodes.append(Team.vertex_to_instance(node))

        return nodes
示例#11
0
    def get_account_admins(cls, account_id):
        """ Returns all Users that are admins of the given account """
        query = f"g.V().has('{Account.LABEL}', 'id', '{account_id}')" + \
            f".in('{cls.LABEL}')"
        result = client.submit(query).all().result()

        return [User.vertex_to_instance(i) for i in result]
示例#12
0
    def get_all_template_inheritors(cls, template_id):
        """ Returns all vertices that inherit from this template id """
        query = f"g.V().has('{Template.LABEL}', 'id', '{template_id}')" + \
            f".in('{cls.LABEL}')"

        res = client.submit(query).all().result()

        return [CoreVertex.vertex_to_instance(i) for i in res]
示例#13
0
    def get_template_properties(cls, template_id):
        """ Returns all TemplateProperties belonging to the given template """
        query = f"g.V().has('{Template.LABEL}', 'id', '{template_id}')" + \
            f".out('{cls.LABEL}')"

        res = client.submit(query).all().result()

        return [TemplateProperty.vertex_to_instance(i) for i in res]
示例#14
0
    def get_users(self):
        """ Returns all users who "hold" this account through the
            UserHoldsAccount edge
        """
        query = f"g.V().has('{self.LABEL}', 'id', '{self.id}')" + \
            f".in('{UserHoldsAccount.LABEL}').hasLabel('{User.LABEL}')"
        r = client.submit(query).all().result()

        return [User.vertex_to_instance(i) for i in r]
示例#15
0
 def get_last_checked_time(user_id, node_id):
     """ Returns the time that this user last checked messages """
     query = f"g.V().has('{auth.User.LABEL}', 'id', '{user_id}')" + \
         f".outE('{UserLastCheckedMessage.LABEL}').as('e')" + \
         f".inV().has('id', '{node_id}').select('e').order()" + \
         f".by('time', decr)"
     result = client.submit(query).all().result()
     if result:
         last_read = UserLastCheckedMessage.edge_to_instance(result[0])
         return last_read
     return None
示例#16
0
    def update_properties_index(cls, property_ids):
        """ Receives a list of property IDs, and updates all of their
            index fields with their index in the given list
        """
        query = f"g.V().hasLabel('{cls.LABEL}').choose(id())"
        for index, prop_id in enumerate(property_ids):
            query += f".option('{prop_id}', property('index', {index}))"

        result = client.submit(query).all().result()

        return [cls.vertex_to_instance(i) for i in result]
示例#17
0
    def get_root(cls, core_vertex_id):
        """ Returns the team vertex at the base of this core-vertex
            ownership tree
            [UNTESTED]
        """
        query = \
            f"g.V().has('{CoreVertex.LABEL}', 'id', '{core_vertex_id}')" + \
            f".until(hasLabel('{Team.LABEL}')).repeat(out('{cls.LABEL}'))"

        team = client.submit(query).all().result()[0]
        return Team.vertex_to_instance(team)
示例#18
0
    def get_user_permissions(self, user_id):
        """ Returns the roles assigned to the given user for this
            Team
        """
        query = f"g.V().has('{self.LABEL}', 'id', '{self.id}')" + \
            f".inE('{auth.UserAssignedToCoreVertex.LABEL}').as('e')" + \
            f".outV().has('{auth.User.LABEL}', 'id', '{user_id}')" + \
            f".select('e')"
        result = client.submit(query).all().result()

        return auth.UserAssignedToCoreVertex.edge_to_instance(result[0]).role \
            if result else None
示例#19
0
    def update(cls, validated_data={}, vertex_id=None):
        """ Updates the template through the base `update` method, as well
            as added functionality for adding (DROPPING + RECREATING) the
            properties
        """
        template_properties = validated_data.pop("properties", [])

        template = super().update(validated_data=validated_data,
                                  vertex_id=vertex_id)

        # Dropping all template properties and recreating them
        if template_properties:
            drop_query = f"g.V().has('{cls.LABEL}', 'id', '{vertex_id}')" + \
                f".out('{TemplateHasProperty.LABEL}').drop()"
            client.submit(drop_query)

            # Recreating the provided template_properties
            create_query = "g.V()" + \
                f".has('{Template.LABEL}', 'id', '{template.id}').as('t')"
            for prop in template_properties:
                # Vertex Create + partition key query
                create_query += f".addV('{TemplateProperty.LABEL}')" + \
                    f".property('{DATABASE_SETTINGS['partition_key']}', " + \
                    f"'{TemplateProperty.LABEL}')"
                # A property call for each field
                for field, field_type in TemplateProperty.properties.items():
                    create_query += f".property('{field}', '{prop[field]}')"
                # The edge linking the template to the property
                create_query += f".addE('{TemplateHasProperty.LABEL}')" + \
                    ".from('t')"
            # Selecting all created properties at the end of the query
            create_query += f".outV().out('{TemplateHasProperty.LABEL}')"

            res = client.submit(create_query).all().result()
            template.properties = [
                TemplateProperty.vertex_to_instance(i) for i in res
            ]

        return template
示例#20
0
    def bulk_update_template_data(cls, nodes):
        """ Bulk updates the template data property for each
            node in the array - format for nodes must be:
                { nodeId: templateDataString }
        """
        query = f"g.V().hasLabel('{cls.LABEL}').choose(id())"
        for node in nodes:
            query += f".option('{node['id']}', " + \
                f"property('templateData', '{node['templateData']}'))"

        result = client.submit(query).all().result()

        return result
示例#21
0
    def get_children_tree(parent_id, user_id):
        """ Returns the children of the given parent node in a tree view
            list format as [ {'name': '...', 'children': [...]} ] with their
            direct sub-children
                - Also returns an isFavorite value for each child
        """
        query = f"g.V().has('id', '{parent_id}').out('owns')" + \
            f".hasLabel('{CoreVertex.LABEL}').as('children')" + \
            f".select('children').by(project('topChild', 'template', 'sub_children')" + \
            f".by()" + \
            f".by(outE('{CoreVertexInheritsFromTemplate.LABEL}').inV())" + \
            f".by(outE('{CoreVertexOwnership.LABEL}').inV()" + \
            f".hasLabel('{CoreVertex.LABEL}').as('subchild')" + \
            f".outE('{CoreVertexInheritsFromTemplate.LABEL}').inV()" + \
            f".as('subchildTemplate').select('subchild')" + \
            f".map(outE('{CoreVertexOwnership.LABEL}').inV()" + \
            f".hasLabel('{CoreVertex.LABEL}').count()).as('childCount')" + \
            f".select('subchild', 'subchildTemplate', 'childCount').fold()))"

        tree = []
        favorite_nodes = UserFavoriteNode.get_favorite_nodes(
            user_id, parent_id=parent_id)
        favorite_nodes = [i.id for i in favorite_nodes]

        # Raises an exception if there are NO direct children
        try:
            result = client.submit(query).all().result()
        except:
            return tree

        for child_data in result:
            child = CoreVertex.vertex_to_instance(child_data["topChild"])
            child.template = CoreVertex.vertex_to_instance(
                child_data["template"])
            child.isFavorite = child.id in favorite_nodes
            sub_children = []

            for sub_child in child_data["sub_children"]:
                cv = CoreVertex.vertex_to_instance(sub_child["subchild"])
                cv.isFavorite = cv.id in favorite_nodes
                cv.template = Template.vertex_to_instance(
                    sub_child["subchildTemplate"])
                if sub_child["childCount"] > 0:
                    cv.children = []
                sub_children.append(cv)
            if sub_children:
                child.children = sub_children

            tree.append(child)

        return tree
示例#22
0
    def get_teams_with_detail(cls, account_id, user_id):
        """ Returns all teams owned by the given account id with its
            own properties as well as the following details:
                - templatesCount,
                - member (array)
                - topicsCount
            -- Returns only the teams the user has access to
            -- SERIALIZED
        """
        query = f"g.V().has('{auth.Account.LABEL}', 'id', '{account_id}')" + \
            f".out('{auth.AccountOwnsTeam.LABEL}').as('team')" + \
            f".inE('{auth.UserAssignedToCoreVertex.LABEL}').outV()" + \
            f".as('member').select('team')" + \
            f".project('templatesCount', 'name', 'id', 'member', 'topicsCount')" + \
            f".by(outE('{TeamOwnsTemplate.LABEL}').inV()" + \
            f".hasLabel('{Template.LABEL}').count())" + \
            f".by(values('name'))" + \
            f".by(values('id'))" + \
            f".by(select('member'))" + \
            f".by(outE('{TeamOwnsTemplate.LABEL}').inV()" + \
            f".hasLabel('{Template.LABEL}')" + \
            f".inE('{CoreVertexInheritsFromTemplate.LABEL}').count())"
        result = client.submit(query).all().result()

        teams = {}
        for team in result:
            if team["id"] not in teams:
                teams[team["id"]] = {
                    "id": team["id"],
                    "name": team["name"],
                    "templatesCount": team["templatesCount"],
                    "topicsCount": team["topicsCount"],
                    "members": []
                }
            member = {
                "id": team["member"]["id"],
                "email": team["member"]["properties"]["email"][0]["value"],
                "avatarLink": ""  # [TODO]
            }
            if member not in teams[team["id"]]["members"]:
                teams[team["id"]]["members"].append(member)

        # Filtering to only teams that this user is a member of
        teams = list(teams.values())
        teams = [
            team for team in teams
            if user_id in [member["id"] for member in team["members"]]
        ]

        return teams
示例#23
0
    def get_held_accounts(cls, user_id, initialize_models=False):
        """ Returns all accounts "held by" (edge) this user or the accounts
             that the user has access to at least one of the teams in

            If the `initialize_models` arg is True, the vertexes are converted
            into Account models before being returned; otherwise they're
            returned as IDs
        """
        user_accounts_q = f"g.V().has('{cls.LABEL}', 'id', '{user_id}')" + \
                           f".as('u').out('{UserHoldsAccount.LABEL}')" + \
                           f".hasLabel('{Account.LABEL}')" + \
                           f".store('accounts').select('u')" + \
                           f".out('{UserAssignedToCoreVertex.LABEL}')" + \
                           f".hasLabel('team').in('{AccountOwnsTeam.LABEL}')" + \
                           f".store('accounts').cap('accounts')" + \
                           f".unfold().dedup()"
        user_accounts = client.submit(user_accounts_q).all().result()

        if initialize_models:
            account_ids = ','.join([f"'{i['id']}'" for i in user_accounts])
            admins_query = f"g.V().has('id', within({account_ids}))" + \
                f".inE('{UserIsAccountAdmin.LABEL}')" + \
                f".project('inV', 'outV')" + \
                f".by(inV()).by(outV())"
            admins = client.submit(admins_query).all().result()
            accounts = []
            for account in user_accounts:
                account = Account.vertex_to_instance(account)
                account.admins = list(
                    map(lambda x: User.vertex_to_instance(x["outV"]),
                        filter(lambda x: x["inV"]["id"] == account.id,
                               admins)))
                accounts.append(account)
            return accounts
        else:
            return [i["id"] for i in user_accounts]
示例#24
0
    def get_user_assigned_role(cls, core_vertex_id, user_id, inv_label=None):
        """ Returns the role (UserAssignedToCoreVertex instance) assigned
            to the user for the given core-vertex
        """
        INV_LABEL = inv_label or cls.INV_LABEL
        query = f"g.V().hasLabel('{INV_LABEL}')" + \
            f".has('id', '{core_vertex_id}').inE('{cls.LABEL}').as('e')" + \
            f".outV().has('id', '{user_id}').select('e')"
        result = client.submit(query).all().result()

        if result:
            result = result[0]
            edge = UserAssignedToCoreVertex.edge_to_instance(result)
            return edge
        return None
示例#25
0
    def get_children(cls, parent_id, parent_type, template_id=None):
        """ Returns all DIRECT children coreVertices under the given
            parent
        """
        query = f"g.V().has('{parent_type}', 'id', '{parent_id}')" + \
            f".out('{cls.LABEL}').hasLabel('{CoreVertex.LABEL}')"

        if template_id:
            query += f".as('cv')" + \
                f".out('{CoreVertexInheritsFromTemplate.LABEL}')" + \
                f".has('id', '{template_id}').select('cv')"

        result = client.submit(query).all().result()

        return [CoreVertex.vertex_to_instance(i) for i in result]
示例#26
0
    def test_user_registration_with_duplicate_email(self):
        """ Tests the user registration endpoint to confirm that
            a user can't be created with an existing email
        """
        # Creating the base user that will be tested against
        result = client.submit(self.create_query).all().result()
        assert result, ValueError("Test Error - Could not "
                                  "create user manually!")

        # Changing the username to confirm the email duplication is checked
        self.user_details["username"] = "******"

        r = self.client.post(self.url, json=self.user_details)
        self.assertEqual(r.status_code, 400)
        self.assertEqual(r.json["error"], "User already exists!")
示例#27
0
    def custom_validation(cls,
                          data,
                          outv_id=None,
                          inv_id=None,
                          outv_label=None,
                          inv_label=None):
        """ Provides custom validation to confirm that:
            1) A Core Vertex only inherits from one template at a time and
            2) Core Vertex only inherits froom a template owned by the vertex's
                team [TODO]
        """
        # Verification for [1]
        existing_template_query = \
            f"g.V().has('{cls.OUTV_LABEL}', 'id', '{outv_id}')" + \
            f".out('{cls.LABEL}')"
        existing_template = client.submit(
            existing_template_query).all().result()
        if existing_template:
            raise CustomValidationFailedException(
                "A CoreVertex can only inherit from a single Template "
                "at a time")

        # Verification for [2]
        team_template_query = \
            f"g.V().has('{CoreVertex.LABEL}', 'id', '{outv_id}')" + \
            f".until(hasLabel('{Team.LABEL}'))" + \
            f".repeat(__.in('{CoreVertexOwnership.LABEL}')).emit()" + \
            f".out('{TeamOwnsTemplate.LABEL}')" + \
            f".has('{Template.LABEL}', 'id', '{inv_id}')"
        template_exists = client.submit(team_template_query).all().result()
        if not template_exists:
            raise CustomValidationFailedException(
                "The provided template either doesn't exist, or is not owned"
                "by the same team as the CoreVertex")

        return data
示例#28
0
    def get_account_with_admins(cls, account_id):
        """ Returns the account details along with the admins of this
            account
        """
        query = f"g.V().has('{cls.LABEL}', 'id', '{account_id}')" + \
            f".fold().project('account', 'admins')" + \
            f".by(unfold())" + \
            f".by(unfold().inE('{UserIsAccountAdmin.LABEL}')" + \
            f".outV().fold())"
        result = client.submit(query).all().result()

        if not result:
            return []
        result = result[0]
        account = Account.vertex_to_instance(result["account"])
        account.admins = [User.vertex_to_instance(i) for i in result["admins"]]
        return account
示例#29
0
    def custom_validation(cls,
                          data,
                          outv_id=None,
                          inv_id=None,
                          outv_label=None,
                          inv_label=None):
        """ Provides validation to confirm that:
            1) A template is only ever owned by one team at a time
        """
        existing_edge_q = f"g.V().has('{cls.INV_LABEL}', 'id', '{inv_id}')" + \
            f".inE('owns')"
        existing_edge = client.submit(existing_edge_q).all().result()
        if existing_edge:
            raise CustomValidationFailedException(
                "Template can only be owned by a single template at a time!")

        return data
示例#30
0
    def put(self, vertex=None, vertex_id=None, **kwargs):
        """ Changes the parent of the given core vertex after removing existing
            parent edge
        """
        data = json.loads(request.data)
        if "newParent" not in data:
            return jsonify_response({
                "status": "New parent not specified"
            }, 400)
        # Moving all of the direct children to the existing parent IF
        # the node has been made a child of one of it's older children
        existing_data_query = f"g.V().has('id', '{vertex.id}')" + \
            f".project('existingParent', 'newParent', 'directChildren')" + \
            f".by(inE('{CoreVertexOwnership.LABEL}').outV())" + \
            f".by(until(has('id', '{data['newParent']}').or().loops().is(30))" + \
            f".repeat(out('{CoreVertexOwnership.LABEL}')).fold())" + \
            f".by(outE('{CoreVertexOwnership.LABEL}').inV().fold())"
        existing_data = client.submit(existing_data_query).all().result()[0]
        old_parent_id = existing_data["existingParent"]["id"]
        existing_direct_children = [CoreVertex.vertex_to_instance(i) for
                                    i in existing_data["directChildren"]]
        new_parent_is_child = len(existing_data["newParent"]) >= 1

        print("Existing Data", existing_data)

        # Updating first level children to have an edge to the old parent
        # if the new parent is a sub-child of the moved node
        if new_parent_is_child:
            print("NEW PARENT IS CHILD")
            children_ids = ",".join(
                [f"'{i.id}'" for i in existing_direct_children])
            children_relocate_query = f"g.V().has('id', within({children_ids}))" + \
                f".inE('{CoreVertexOwnership.LABEL}').drop()"
            client.submit(children_relocate_query).all().result()

            children_relocate_query = f"g.V().has('id', '{old_parent_id}')"
            for index, child in enumerate(existing_direct_children):
                children_relocate_query += f".addE('{CoreVertexOwnership.LABEL}')" + \
                    f".to(g.V().has('id', '{child.id}'))"
                children_relocate_query += ".outV()"
            client.submit(children_relocate_query).all().result()

        # Removing the existing parent edge, and adding the new edge
        query = f"g.V().has('id', '{vertex.id}').as('node')" + \
            f".inE('{CoreVertexOwnership.LABEL}').as('existingEdge')" + \
            f".inV().addE('{CoreVertexOwnership.LABEL}')" + \
            f".from(g.V().has('id', '{data['newParent']}'))" + \
            f".select('existingEdge').drop()"
        res = client.submit(query).all().result()

        return jsonify_response({
            "status": "Success"
        }, 200)