Skip to content

Commit

Permalink
Merge pull request #1053 from vantage6/change/remove-option-to-patch-…
Browse files Browse the repository at this point in the history
…nodes-org-and-collab

Remove option to change organization and collaboration id of existing…
  • Loading branch information
bartvanb committed Mar 6, 2024
2 parents 5848656 + 5c1289d commit ba66a30
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 96 deletions.
29 changes: 9 additions & 20 deletions vantage6-client/vantage6/client/__init__.py
Expand Up @@ -668,13 +668,7 @@ def create(
)

@post_filtering(iterable=False)
def update(
self,
id_: int,
name: str = None,
organization: int = None,
collaboration: int = None,
) -> dict:
def update(self, id_: int, name: str = None, clear_ip: bool = None) -> dict:
"""Update node information
Parameters
Expand All @@ -683,28 +677,23 @@ def update(
Id of the node you want to update
name : str, optional
New node name, by default None
organization : int, optional
Change the owning organization of the node, by default
None
collaboration : int, optional
Changes the collaboration to which the node belongs, by
default None
clear_ip : bool, optional
Clear the VPN IP address of the node, by default None
Returns
-------
dict
Containing the meta-data of the updated node
"""
# note that we are explicitly NOT using the parent's collaboration_id
# here as usually people don't want to change a node's collaboration id
data = {
"name": name,
}
if clear_ip is not None:
data["clear_ip"] = clear_ip
return self.parent.request(
f"node/{id_}",
method="patch",
json={
"name": name,
"organization_id": organization,
"collaboration_id": collaboration,
},
json=data,
)

def delete(self, id_: int) -> dict:
Expand Down
35 changes: 10 additions & 25 deletions vantage6-server/tests_server/test_resources.py
Expand Up @@ -2863,47 +2863,33 @@ def test_patch_node_permissions_as_user(self):
)
self.assertEqual(results.status_code, HTTPStatus.UNAUTHORIZED)

# test updatin the `organization_id` with organization permissions
org2 = Organization()
org2.save()
# test updating the `organization_id` (which is not allowed)
results = self.app.patch(
f"/api/node/{node.id}", headers=headers, json={"organization_id": org2.id}
)
self.assertEqual(results.status_code, HTTPStatus.UNAUTHORIZED)
self.assertEqual(results.status_code, HTTPStatus.BAD_REQUEST)

# test assigning it to a node thats not part of the collaborat
col2 = Collaboration(organizations=[org2])
col2.save()
# test updating the collaboration_id (which is not allowed)
results = self.app.patch(
f"/api/node/{node.id}", headers=headers, json={"collaboration_id": col2.id}
f"/api/node/{node.id}", headers=headers, json={"collaboration_id": col.id}
)
self.assertEqual(results.status_code, HTTPStatus.UNAUTHORIZED)
self.assertEqual(results.status_code, HTTPStatus.BAD_REQUEST)

# collaboration_id and organization_id. Note that the organization
# is assigned before the collaboration is defined.
# try to patch the node's VPN IP address
rule = Rule.get_by_("node", Scope.GLOBAL, Operation.EDIT)
headers = self.create_user_and_login(org2, rules=[rule])
results = self.app.patch(
f"/api/node/{node.id}",
headers=headers,
json={"collaboration_id": col2.id, "organization_id": org2.id},
)
self.assertEqual(results.status_code, HTTPStatus.OK)
self.assertEqual(results.json["organization"]["id"], org2.id)
self.assertEqual(results.json["collaboration"]["id"], col2.id)

# try to patch the node's VPN IP address
results = self.app.patch(
f"/api/node/{node.id}", headers=headers, json={"ip": "0.0.0.0"}
)
self.assertEqual(results.status_code, HTTPStatus.OK)
self.assertEqual(results.json["ip"], "0.0.0.0")

# assign unknow organization
# try to clear the node's VPN IP address - this should work
results = self.app.patch(
f"/api/node/{node.id}", headers=headers, json={"organization_id": 9999}
f"/api/node/{node.id}", headers=headers, json={"clear_ip": True}
)
self.assertEqual(results.status_code, HTTPStatus.NOT_FOUND)
self.assertEqual(results.status_code, HTTPStatus.OK)
self.assertEqual(results.json["ip"], None)

# collaboration permission - inside the collaboration
rule = Rule.get_by_("node", Scope.COLLABORATION, Operation.EDIT)
Expand All @@ -2928,7 +2914,6 @@ def test_patch_node_permissions_as_user(self):
org2.delete()
org3.delete()
col.delete()
col2.delete()

def test_view_task_permissions_as_user(self):
# non existing task
Expand Down
58 changes: 7 additions & 51 deletions vantage6-server/vantage6/server/resource/node.py
Expand Up @@ -571,12 +571,6 @@ def patch(self, id):
application/json:
schema:
properties:
collaboration_id:
type: integer
description: Collaboration id
organization_id:
type: integer
description: Organization id
name:
type: string
description: Node name
Expand Down Expand Up @@ -611,6 +605,13 @@ def patch(self, id):
"msg": "Request body is incorrect",
"errors": errors,
}, HTTPStatus.BAD_REQUEST
# for patching, organization_id and collaboration_id are not allowed fields
if "organization_id" in data:
return {"msg": "Organization id cannot be updated!"}, HTTPStatus.BAD_REQUEST
elif "collaboration_id" in data:
return {
"msg": "Collaboration id cannot be updated!"
}, HTTPStatus.BAD_REQUEST

node = db.Node.get(id)
if not node:
Expand All @@ -630,51 +631,6 @@ def patch(self, id):
}, HTTPStatus.BAD_REQUEST
node.name = name

# organization goes before collaboration (!)
org_id = data.get("organization_id")
updated_org = org_id and org_id != node.organization.id
if updated_org:
if not self.r.e_glo.can():
return {
"msg": "You lack the permission to do that!"
}, HTTPStatus.UNAUTHORIZED
organization = db.Organization.get(data["organization_id"])
if not organization:
return {
"msg": f'Organization id={data["organization_id"]} ' "not found!"
}, HTTPStatus.NOT_FOUND
node.organization = organization

auth = self.obtain_auth()
col_id = data.get("collaboration_id")
updated_col = col_id and col_id != node.collaboration.id
if updated_col:
collaboration = db.Collaboration.get(col_id)
if not collaboration:
return {
"msg": f"collaboration id={col_id} not found!"
}, HTTPStatus.NOT_FOUND

if not self.r.e_glo.can():
if auth.organization not in collaboration.organizations:
return {
"msg": f"Organization id={auth.organization.id} "
"of this node is not part of this collaboration id"
f"={collaboration.id}"
}

node.collaboration = collaboration

# validate that node does not already exist when we change either
# the organization and/or collaboration
if updated_org or updated_col:
if db.Node.exists_by_id(node.organization.id, node.collaboration.id):
return {
"msg": "A node with organization id="
f"{node.organization.id} and collaboration id="
f"{node.collaboration.id} already exists!"
}, HTTPStatus.BAD_REQUEST

# update node IP address if it is given
ip = data.get("ip")
if ip:
Expand Down

0 comments on commit ba66a30

Please sign in to comment.