| Server IP : 3.147.158.171 / Your IP : 216.73.216.229 Web Server : Apache/2.4.67 (Amazon Linux) OpenSSL/3.5.5 System : Linux ip-172-31-2-178.us-east-2.compute.internal 6.1.172-216.329.amzn2023.x86_64 #1 SMP PREEMPT_DYNAMIC Wed May 20 06:31:34 UTC 2026 x86_64 User : ec2-user ( 1000) PHP Version : 8.4.21 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /tsai/www/html/api.johnturman.net/tests/unit/ |
Upload File : |
"""Unit tests for WpService.validate_token — the Article Studio's auth gate.
Two jwt-auth plugin response shapes are in the wild and our sites run both. The
older one (which our local dev WordPress returns) has no `success` field, so a
check for `success` alone rejects perfectly valid tokens and locks every user
out of the studio. Both shapes are pinned here.
"""
from unittest.mock import MagicMock, patch
import requests
from app.appTypes import SiteConfig
from app.services.wp import WpService
def make_site() -> SiteConfig:
return SiteConfig(
cb_host="chat.foo.test", api_host="http://api.foo.test", wp_host="http://foo.test",
wp_dir="foo", drupal_host="http://drupal.test", drupal_api="/jsonapi",
slug="foo", drupal_uid="user-uuid", drupal_target_id=5,
)
def fake_response(status: int, payload=None, raises: bool = False) -> MagicMock:
resp = MagicMock()
resp.status_code = status
if raises:
resp.json.side_effect = ValueError("not json")
else:
resp.json.return_value = payload or {}
return resp
def run_validate(response=None, side_effect=None, token="a-token"):
with patch("app.services.wp.requests.post", return_value=response,
side_effect=side_effect) as post:
result = WpService().validate_token(make_site(), token)
return result, post
def test_accepts_older_plugin_shape_without_success_field():
"""HTTP 200 + jwt_auth_valid_token, no `success` key — our dev WordPress."""
result, _ = run_validate(fake_response(200, {
"code": "jwt_auth_valid_token", "data": {"status": 200},
}))
assert result is not None
def test_accepts_newer_plugin_shape_with_success_field():
result, _ = run_validate(fake_response(200, {
"success": True, "code": "jwt_auth_valid_token", "data": {"status": 200},
}))
assert result is not None
def test_rejects_forbidden_token():
"""An invalid or foreign-site token comes back 403."""
result, _ = run_validate(fake_response(403, {
"code": "jwt_auth_invalid_token", "message": "Wrong number of segments",
}))
assert result is None
def test_rejects_missing_token_without_calling_wordpress():
for token in (None, ""):
result, post = run_validate(fake_response(200, {"code": "jwt_auth_valid_token"}),
token=token)
assert result is None
post.assert_not_called()
def test_rejects_unrecognized_200_body():
"""Fail closed: an auth gate must not pass a body it does not understand."""
result, _ = run_validate(fake_response(200, {"code": "something_else"}))
assert result is None
def test_rejects_non_json_and_network_errors():
result, _ = run_validate(fake_response(200, raises=True))
assert result is None
result, _ = run_validate(side_effect=requests.RequestException("boom"))
assert result is None
def test_validates_against_the_given_sites_wordpress():
"""The request must go to this site's host — that is what scopes the token."""
_, post = run_validate(fake_response(200, {"code": "jwt_auth_valid_token"}))
url = post.call_args.args[0]
assert url == "http://foo.test/wp-json/jwt-auth/v1/token/validate"
assert post.call_args.kwargs["headers"]["Authorization"] == "Bearer a-token"