import pytest from app.chis.auth import ChisLoginClient, ChisLoginError class FakeTransport: def __init__(self, responses): self.responses = list(responses) self.calls = [] def post(self, url, headers, payload): self.calls.append({"url": url, "headers": headers, "payload": payload}) return self.responses.pop(0) def fake_encrypt(public_key, raw_text): if raw_text == "secret": return "encrypted-password" if raw_text == "1234567890": return "encrypted-time" return "encrypted-value" def test_login_gets_role_apps_and_cookie_without_leaking_password(): transport = FakeTransport( [ ( { "code": 200, "body": { "tokens": [ {"roleName": "其他角色", "id": "1", "userName": "ignored"}, {"roleName": "责任医生", "id": "role-2", "userName": "doctor"}, ] }, }, {"Set-Cookie": "JSESSIONID=abc123; Path=/chis; HttpOnly"}, ), ({"code": 200, "body": {"apps": []}}, {}), ] ) client = ChisLoginClient( base_url="http://chis.example.test/chis", public_key="public-key", transport=transport, encrypt=fake_encrypt, now_millis=lambda: 1234567890, ) session = client.login(username="u001", password="secret") assert session.cookie == "JSESSIONID=abc123; sessionId1=abc123; u001=%E8%B4%A3%E4%BB%BB%E5%8C%BB%E7%94%9F@photo/default.jpg" assert session.role_id == "role-2" assert session.role_name == "责任医生" assert session.user_name == "doctor" assert transport.calls[0]["url"] == "http://chis.example.test/chis/logon/myRoles" assert transport.calls[0]["payload"] == { "url": "logon/myRoles", "uid": "u001", "pwd": "encrypted-password", "d": "encrypted-time", } assert "secret" not in str(transport.calls) assert transport.calls[1]["url"].startswith("http://chis.example.test/chis/logon/myApps?") assert transport.calls[1]["headers"]["Cookie"] == "JSESSIONID=abc123" assert "urt=role-2" in transport.calls[1]["url"] def test_login_raises_clear_error_when_roles_fail(): transport = FakeTransport([({"code": 501, "msg": "PasswordNotRight"}, {})]) client = ChisLoginClient( base_url="http://chis.example.test/chis", public_key="public-key", transport=transport, encrypt=fake_encrypt, ) with pytest.raises(ChisLoginError) as exc_info: client.login(username="u001", password="secret") assert exc_info.value.code == "chis_login_failed" assert "PasswordNotRight" in str(exc_info.value) assert "secret" not in str(exc_info.value) def test_login_raises_clear_error_when_required_role_missing(): transport = FakeTransport( [ ( { "code": 200, "body": { "tokens": [ {"roleName": "其他角色", "id": "1", "userName": "ignored"}, ] }, }, {"Set-Cookie": "JSESSIONID=abc123; Path=/chis"}, ), ] ) client = ChisLoginClient( base_url="http://chis.example.test/chis", public_key="public-key", transport=transport, encrypt=fake_encrypt, ) with pytest.raises(ChisLoginError) as exc_info: client.login(username="u001", password="secret") assert exc_info.value.code == "chis_role_not_allowed" assert "责任医生助理" in str(exc_info.value) assert "责任医生" in str(exc_info.value) def test_requests_transport_uses_proxy_when_configured(): client = ChisLoginClient.from_config( { "CHIS_BASE_URL": "http://chis.example.test/chis", "CHIS_PUBLIC_KEY": "public-key", "CHIS_PROXY": "socks5h://127.0.0.1:1080", } ) assert client.transport.session.proxies["http"] == "socks5h://127.0.0.1:1080" assert client.transport.session.proxies["https"] == "socks5h://127.0.0.1:1080" def test_requests_transport_direct_when_proxy_empty(): client = ChisLoginClient.from_config( { "CHIS_BASE_URL": "http://chis.example.test/chis", "CHIS_PUBLIC_KEY": "public-key", "CHIS_PROXY": "", } ) assert client.transport.session.proxies == {} def test_login_client_accepts_plain_host_config(): client = ChisLoginClient( base_url="chis.example.test:9002", public_key="public-key", transport=FakeTransport([]), encrypt=fake_encrypt, ) assert client.base_url == "http://chis.example.test:9002/chis" assert client.host == "chis.example.test:9002"