mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-11-03 10:36:45 +09:00
Pairing /claim creates a fleet server and /lookup reveals a pending agent's details; both were @jwt_required() only, so any authenticated user (incl. a read-only viewer) could use them. Gate both with @developer_required to match POST /servers. Test: viewer 403, developer clears the gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""
|
|
Authorization test for audit L1: pairing claim/lookup create or reveal fleet
|
|
servers, so they should require developer role for consistency with
|
|
POST /api/v1/servers (@developer_required) — not just any authenticated user.
|
|
"""
|
|
from flask_jwt_extended import create_access_token
|
|
from werkzeug.security import generate_password_hash
|
|
|
|
from app import db
|
|
from app.models import User
|
|
|
|
|
|
def _user(role):
|
|
u = User(
|
|
email=f"{role}@pair.local",
|
|
username=f"{role}-pair",
|
|
password_hash=generate_password_hash("x"),
|
|
role=role,
|
|
is_active=True,
|
|
)
|
|
db.session.add(u)
|
|
db.session.commit()
|
|
return u
|
|
|
|
|
|
def _headers(user):
|
|
return {"Authorization": f"Bearer {create_access_token(identity=user.id)}"}
|
|
|
|
|
|
def test_viewer_cannot_lookup_or_claim(client, app):
|
|
with app.app_context():
|
|
headers = _headers(_user(User.ROLE_VIEWER))
|
|
|
|
r1 = client.post("/api/v1/pairing/lookup", headers=headers, json={"code": "ABC123"})
|
|
assert r1.status_code == 403, r1.get_data(as_text=True)
|
|
|
|
r2 = client.post("/api/v1/pairing/claim", headers=headers,
|
|
json={"code": "ABC123", "passphrase": "pw"})
|
|
assert r2.status_code == 403, r2.get_data(as_text=True)
|
|
|
|
|
|
def test_developer_clears_the_role_gate(client, app):
|
|
"""A developer passes the role gate; lookup then 404s (no such code),
|
|
which proves the gate let them through rather than blocking with 403."""
|
|
with app.app_context():
|
|
headers = _headers(_user(User.ROLE_DEVELOPER))
|
|
|
|
r = client.post("/api/v1/pairing/lookup", headers=headers, json={"code": "NOSUCH"})
|
|
assert r.status_code != 403, r.get_data(as_text=True)
|
|
assert r.status_code == 404, r.get_data(as_text=True)
|