""" Scenarios 19, 22, 23, 24: Admin role access and peer management. Tests cover: - Admin can read configuration and list peers - Admin is blocked from peer-only routes (/api/peer/*) - Peer creation validation (missing/weak password) - Full create-and-delete peer lifecycle - Admin can list auth users """ import pytest # --------------------------------------------------------------------------- # Read access # --------------------------------------------------------------------------- def test_admin_can_get_config(admin_client): r = admin_client.get('/api/config') assert r.status_code == 200, ( f"Admin should be able to GET /api/config, got {r.status_code}" ) data = r.json() # Config must contain at least one well-known top-level key assert 'cell_name' in data or 'service_configs' in data or 'ip_range' in data, ( f"Config response missing expected keys: {list(data.keys())}" ) def test_admin_can_list_peers(admin_client): r = admin_client.get('/api/peers') assert r.status_code == 200, ( f"Admin should be able to GET /api/peers, got {r.status_code}" ) assert isinstance(r.json(), list), ( f"GET /api/peers should return a list, got {type(r.json())}" ) # --------------------------------------------------------------------------- # Peer-only routes must be blocked for admin # --------------------------------------------------------------------------- def test_admin_cannot_access_peer_dashboard(admin_client): r = admin_client.get('/api/peer/dashboard') assert r.status_code == 403, ( f"Admin should be blocked from /api/peer/dashboard with 403, got {r.status_code}" ) def test_admin_cannot_access_peer_services(admin_client): r = admin_client.get('/api/peer/services') assert r.status_code == 403, ( f"Admin should be blocked from /api/peer/services with 403, got {r.status_code}" ) # --------------------------------------------------------------------------- # Peer creation validation # --------------------------------------------------------------------------- def test_create_peer_missing_password(admin_client): """POST /api/peers with name + public_key but no password must return 400.""" # Use a fixed throwaway key; it doesn't need to be a real WireGuard key for # validation tests — the password check should happen before key verification. r = admin_client.post('/api/peers', json={ 'name': 'e2etest-no-password', 'public_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', }) assert r.status_code == 400, ( f"Creating peer without password should return 400, got {r.status_code}" ) def test_create_peer_short_password(admin_client): """POST /api/peers with a 5-character password must return 400.""" r = admin_client.post('/api/peers', json={ 'name': 'e2etest-short-pass', 'public_key': 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=', 'password': 'Ab1!x', }) assert r.status_code == 400, ( f"Creating peer with 5-char password should return 400, got {r.status_code}" ) # --------------------------------------------------------------------------- # Full create and delete lifecycle # --------------------------------------------------------------------------- def test_create_and_delete_peer(admin_client, make_peer): """Create a peer, verify it appears in the list, delete it, verify it's gone.""" peer = make_peer('e2etest-lifecycle') # Peer must appear in the list r = admin_client.get('/api/peers') assert r.status_code == 200 peers = r.json() names = [p.get('peer') or p.get('name', '') for p in peers] assert 'e2etest-lifecycle' in names, ( f"Newly created peer 'e2etest-lifecycle' not found in /api/peers: {names}" ) # Delete the peer manually (make_peer's finalizer will also attempt deletion) r = admin_client.delete('/api/peers/e2etest-lifecycle') assert r.status_code == 200, ( f"DELETE /api/peers/e2etest-lifecycle should return 200, got {r.status_code}" ) # Verify it's gone r = admin_client.get('/api/peers') assert r.status_code == 200 peers_after = r.json() names_after = [p.get('peer') or p.get('name', '') for p in peers_after] assert 'e2etest-lifecycle' not in names_after, ( f"Deleted peer 'e2etest-lifecycle' still appears in /api/peers: {names_after}" ) # --------------------------------------------------------------------------- # Auth user management # --------------------------------------------------------------------------- def test_admin_can_list_auth_users(admin_client): r = admin_client.get('/api/auth/users') assert r.status_code == 200, ( f"Admin should be able to GET /api/auth/users, got {r.status_code}" ) users = r.json() assert isinstance(users, list), ( f"GET /api/auth/users should return a list, got {type(users)}" ) usernames = [u.get('username') for u in users] assert 'admin' in usernames, ( f"'admin' not found in user list: {usernames}" )