feat: allow admins to bypass approval flow when joining networks
This commit is contained in:
@@ -201,3 +201,145 @@ class TestZeroTierMembership:
|
||||
except ApiError as exc:
|
||||
# Accept errors when no active memberships to kill
|
||||
assert exc.status_code in (400, 500)
|
||||
|
||||
|
||||
class TestAdminUserDevices:
|
||||
"""Test admin endpoint to list devices for a specific user."""
|
||||
|
||||
def test_list_user_devices_positive(
|
||||
self, integration_client, create_test_user, create_test_org, create_test_membership, integration_app
|
||||
):
|
||||
"""TEST: ZT-10 — Admin lists devices for a user with devices.
|
||||
|
||||
WHAT: Admin GET /organizations/<id>/users/<user_id>/devices.
|
||||
WHY: Admins need to see what devices a user has registered.
|
||||
EXPECTED: 200 OK with devices array.
|
||||
"""
|
||||
from gatehouse_app.models.zerotier.device import Device
|
||||
|
||||
admin = create_test_user(password="AdminPass123!")
|
||||
member = create_test_user(password="MemberPass123!")
|
||||
org = create_test_org()
|
||||
|
||||
create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN)
|
||||
create_test_membership(member["id"], org["id"], OrganizationRole.MEMBER)
|
||||
|
||||
# Create test devices for the member
|
||||
from gatehouse_app.extensions import db as _db
|
||||
with integration_app.app_context():
|
||||
device1 = Device(
|
||||
user_id=member["id"],
|
||||
organization_id=org["id"],
|
||||
node_id="1234567890",
|
||||
device_nickname="Member Laptop",
|
||||
hostname="member-laptop",
|
||||
)
|
||||
device2 = Device(
|
||||
user_id=member["id"],
|
||||
organization_id=org["id"],
|
||||
node_id="0987654321",
|
||||
device_nickname="Member Phone",
|
||||
hostname="member-phone",
|
||||
)
|
||||
_db.session.add_all([device1, device2])
|
||||
_db.session.commit()
|
||||
|
||||
integration_client.auth.login(email=admin["email"], password="AdminPass123!")
|
||||
result = integration_client.get(f"/organizations/{org['id']}/users/{member['id']}/devices")
|
||||
data = assert_success(result, "devices retrieved")
|
||||
|
||||
assert "devices" in data
|
||||
assert data["count"] == 2
|
||||
assert data["user_id"] == member["id"]
|
||||
assert data["organization_id"] == org["id"]
|
||||
device_node_ids = [d["node_id"] for d in data["devices"]]
|
||||
assert "1234567890" in device_node_ids
|
||||
assert "0987654321" in device_node_ids
|
||||
|
||||
def test_list_user_devices_no_devices(
|
||||
self, integration_client, create_test_user, create_test_org, create_test_membership
|
||||
):
|
||||
"""TEST: ZT-11 — Admin lists devices for a user with no devices.
|
||||
|
||||
WHAT: Admin GET /organizations/<id>/users/<user_id>/devices for user with no devices.
|
||||
WHY: Endpoint should return empty list, not error.
|
||||
EXPECTED: 200 OK with empty devices array.
|
||||
"""
|
||||
admin = create_test_user(password="AdminPass123!")
|
||||
member = create_test_user(password="MemberPass123!")
|
||||
org = create_test_org()
|
||||
|
||||
create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN)
|
||||
create_test_membership(member["id"], org["id"], OrganizationRole.MEMBER)
|
||||
|
||||
integration_client.auth.login(email=admin["email"], password="AdminPass123!")
|
||||
result = integration_client.get(f"/organizations/{org['id']}/users/{member['id']}/devices")
|
||||
data = assert_success(result)
|
||||
|
||||
assert data["count"] == 0
|
||||
assert data["devices"] == []
|
||||
|
||||
def test_list_user_devices_non_admin_negative(
|
||||
self, integration_client, create_test_user, create_test_org, create_test_membership
|
||||
):
|
||||
"""TEST: ZT-12 — Non-admin cannot list another user's devices.
|
||||
|
||||
WHAT: Member attempts GET /organizations/<id>/users/<user_id>/devices.
|
||||
WHY: This endpoint is admin-only.
|
||||
EXPECTED: 403 Forbidden.
|
||||
"""
|
||||
member1 = create_test_user(password="Member1Pass123!")
|
||||
member2 = create_test_user(password="Member2Pass123!")
|
||||
org = create_test_org()
|
||||
|
||||
create_test_membership(member1["id"], org["id"], OrganizationRole.MEMBER)
|
||||
create_test_membership(member2["id"], org["id"], OrganizationRole.MEMBER)
|
||||
|
||||
integration_client.auth.login(email=member1["email"], password="Member1Pass123!")
|
||||
with pytest.raises(ApiError) as exc_info:
|
||||
integration_client.get(f"/organizations/{org['id']}/users/{member2['id']}/devices")
|
||||
assert exc_info.value.status_code == 403
|
||||
|
||||
def test_list_user_devices_user_not_in_org_negative(
|
||||
self, integration_client, create_test_user, create_test_org, create_test_membership
|
||||
):
|
||||
"""TEST: ZT-13 — Cannot list devices for user not in organization.
|
||||
|
||||
WHAT: Admin GET /organizations/<id>/users/<user_id>/devices for user not in org.
|
||||
WHY: User must be a member of the organization.
|
||||
EXPECTED: 404 Not Found.
|
||||
"""
|
||||
admin = create_test_user(password="AdminPass123!")
|
||||
outside_user = create_test_user(password="OutsidePass123!")
|
||||
org = create_test_org()
|
||||
|
||||
create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN)
|
||||
# outside_user is NOT added to the org
|
||||
|
||||
integration_client.auth.login(email=admin["email"], password="AdminPass123!")
|
||||
with pytest.raises(ApiError) as exc_info:
|
||||
integration_client.get(f"/organizations/{org['id']}/users/{outside_user['id']}/devices")
|
||||
assert exc_info.value.status_code == 404
|
||||
|
||||
def test_list_user_devices_user_not_found_negative(
|
||||
self, integration_client, create_test_user, create_test_org, create_test_membership
|
||||
):
|
||||
"""TEST: ZT-14 — Cannot list devices for non-existent user.
|
||||
|
||||
WHAT: Admin GET /organizations/<id>/users/<non_existent_id>/devices.
|
||||
WHY: User must exist.
|
||||
EXPECTED: 404 Not Found.
|
||||
"""
|
||||
import uuid
|
||||
|
||||
admin = create_test_user(password="AdminPass123!")
|
||||
org = create_test_org()
|
||||
|
||||
create_test_membership(admin["id"], org["id"], OrganizationRole.ADMIN)
|
||||
|
||||
non_existent_id = str(uuid.uuid4())
|
||||
|
||||
integration_client.auth.login(email=admin["email"], password="AdminPass123!")
|
||||
with pytest.raises(ApiError) as exc_info:
|
||||
integration_client.get(f"/organizations/{org['id']}/users/{non_existent_id}/devices")
|
||||
assert exc_info.value.status_code == 404
|
||||
|
||||
Reference in New Issue
Block a user