mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-09-05 23:47:33 +08:00
fix: prevent secondary OTP from hanging
This commit is contained in:
@@ -1073,12 +1073,11 @@ class RegistrationEngine:
|
|||||||
self._log("未能重新进入登录流程", "warning")
|
self._log("未能重新进入登录流程", "warning")
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
password_ok, _ = self._submit_login_password_step_and_get_continue_url()
|
|
||||||
if not password_ok:
|
|
||||||
return None, None
|
|
||||||
|
|
||||||
self._otp_sent_at = time.time()
|
self._otp_sent_at = time.time()
|
||||||
|
|
||||||
|
if not self._submit_login_password_step():
|
||||||
|
return None, None
|
||||||
|
|
||||||
code = self._get_verification_code()
|
code = self._get_verification_code()
|
||||||
if not code:
|
if not code:
|
||||||
self._log("登录流程获取验证码失败", "warning")
|
self._log("登录流程获取验证码失败", "warning")
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ from ..config.constants import OTP_CODE_PATTERN
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
OTP_SENT_AT_TOLERANCE_SECONDS = 2
|
||||||
|
|
||||||
|
|
||||||
class TempmailService(BaseEmailService):
|
class TempmailService(BaseEmailService):
|
||||||
"""
|
"""
|
||||||
@@ -184,7 +186,7 @@ class TempmailService(BaseEmailService):
|
|||||||
email_id: 邮箱 token(如果不提供,从缓存中查找)
|
email_id: 邮箱 token(如果不提供,从缓存中查找)
|
||||||
timeout: 超时时间(秒)
|
timeout: 超时时间(秒)
|
||||||
pattern: 验证码正则表达式
|
pattern: 验证码正则表达式
|
||||||
otp_sent_at: OTP 发送时间戳,只允许使用严格晚于该锚点的邮件
|
otp_sent_at: OTP 发送时间戳,只允许使用严格晚于该锚点减去容差后的邮件
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
验证码字符串,如果超时或未找到返回 None
|
验证码字符串,如果超时或未找到返回 None
|
||||||
@@ -241,7 +243,8 @@ class TempmailService(BaseEmailService):
|
|||||||
|
|
||||||
msg_timestamp = self._get_received_timestamp(msg)
|
msg_timestamp = self._get_received_timestamp(msg)
|
||||||
if otp_sent_at is not None:
|
if otp_sent_at is not None:
|
||||||
if msg_timestamp is None or msg_timestamp <= otp_sent_at:
|
min_allowed_timestamp = otp_sent_at - OTP_SENT_AT_TOLERANCE_SECONDS
|
||||||
|
if msg_timestamp is None or msg_timestamp <= min_allowed_timestamp:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
message_id = str(
|
message_id = str(
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ def test_phase_otp_secondary_returns_dedicated_timeout_error_code(monkeypatch):
|
|||||||
assert engine.phase_history[0].error_code == ERROR_OTP_TIMEOUT_SECONDARY
|
assert engine.phase_history[0].error_code == ERROR_OTP_TIMEOUT_SECONDARY
|
||||||
|
|
||||||
|
|
||||||
def test_advance_login_authorization_refreshes_otp_anchor_after_password_submit(monkeypatch):
|
def test_advance_login_authorization_sets_otp_anchor_before_password_submit(monkeypatch):
|
||||||
email_service = FakeEmailService(code=None)
|
email_service = FakeEmailService(code=None)
|
||||||
engine = _build_engine(monkeypatch, email_service)
|
engine = _build_engine(monkeypatch, email_service)
|
||||||
engine.oauth_start = object()
|
engine.oauth_start = object()
|
||||||
@@ -82,14 +82,15 @@ def test_advance_login_authorization_refreshes_otp_anchor_after_password_submit(
|
|||||||
monkeypatch.setattr(engine, "_start_oauth", lambda: True)
|
monkeypatch.setattr(engine, "_start_oauth", lambda: True)
|
||||||
monkeypatch.setattr(engine, "_get_device_id", lambda: True)
|
monkeypatch.setattr(engine, "_get_device_id", lambda: True)
|
||||||
monkeypatch.setattr(engine, "_try_reenter_login_flow", lambda: True)
|
monkeypatch.setattr(engine, "_try_reenter_login_flow", lambda: True)
|
||||||
monkeypatch.setattr(
|
|
||||||
engine,
|
|
||||||
"_submit_login_password_step_and_get_continue_url",
|
|
||||||
lambda: (True, "https://continue.example.test"),
|
|
||||||
)
|
|
||||||
|
|
||||||
seen_anchors = []
|
seen_anchors = []
|
||||||
|
|
||||||
|
def fake_submit_login_password_step():
|
||||||
|
seen_anchors.append(engine._otp_sent_at)
|
||||||
|
return True
|
||||||
|
|
||||||
|
monkeypatch.setattr(engine, "_submit_login_password_step", fake_submit_login_password_step)
|
||||||
|
|
||||||
def fake_get_verification_code():
|
def fake_get_verification_code():
|
||||||
seen_anchors.append(engine._otp_sent_at)
|
seen_anchors.append(engine._otp_sent_at)
|
||||||
return None
|
return None
|
||||||
@@ -101,4 +102,4 @@ def test_advance_login_authorization_refreshes_otp_anchor_after_password_submit(
|
|||||||
assert workspace_id is None
|
assert workspace_id is None
|
||||||
assert callback_url is None
|
assert callback_url is None
|
||||||
assert engine._otp_sent_at == 456.0
|
assert engine._otp_sent_at == 456.0
|
||||||
assert seen_anchors == [456.0]
|
assert seen_anchors == [456.0, 456.0]
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class FakeHTTPClient:
|
|||||||
return self.responses.pop(0)
|
return self.responses.pop(0)
|
||||||
|
|
||||||
|
|
||||||
def test_get_verification_code_ignores_messages_not_newer_than_otp_anchor(monkeypatch):
|
def test_get_verification_code_ignores_messages_older_than_tolerance_window(monkeypatch):
|
||||||
service = TempmailService({
|
service = TempmailService({
|
||||||
"base_url": "https://api.tempmail.test/v2",
|
"base_url": "https://api.tempmail.test/v2",
|
||||||
"timeout": 1,
|
"timeout": 1,
|
||||||
@@ -43,7 +43,7 @@ def test_get_verification_code_ignores_messages_not_newer_than_otp_anchor(monkey
|
|||||||
"from": "noreply@openai.com",
|
"from": "noreply@openai.com",
|
||||||
"subject": "Old verification code",
|
"subject": "Old verification code",
|
||||||
"body": "111111",
|
"body": "111111",
|
||||||
"received_at": 1999,
|
"received_at": 1998,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "new-mail",
|
"id": "new-mail",
|
||||||
@@ -74,3 +74,47 @@ def test_get_verification_code_ignores_messages_not_newer_than_otp_anchor(monkey
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def test_get_verification_code_allows_two_second_anchor_tolerance(monkeypatch):
|
||||||
|
service = TempmailService({
|
||||||
|
"base_url": "https://api.tempmail.test/v2",
|
||||||
|
"timeout": 1,
|
||||||
|
"max_retries": 1,
|
||||||
|
})
|
||||||
|
service._email_cache["tester@example.com"] = {
|
||||||
|
"email": "tester@example.com",
|
||||||
|
"token": "token-1",
|
||||||
|
}
|
||||||
|
service.http_client = FakeHTTPClient([
|
||||||
|
FakeResponse(
|
||||||
|
status_code=200,
|
||||||
|
payload={
|
||||||
|
"emails": [
|
||||||
|
{
|
||||||
|
"id": "too-old-mail",
|
||||||
|
"from": "noreply@openai.com",
|
||||||
|
"subject": "Too old verification code",
|
||||||
|
"body": "111111",
|
||||||
|
"received_at": 1998,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "tolerated-mail",
|
||||||
|
"from": "noreply@openai.com",
|
||||||
|
"subject": "Tolerated verification code",
|
||||||
|
"body": "654321",
|
||||||
|
"received_at": 1999,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
])
|
||||||
|
monkeypatch.setattr(tempmail_module.time, "sleep", lambda _: None)
|
||||||
|
|
||||||
|
code = service.get_verification_code(
|
||||||
|
email="tester@example.com",
|
||||||
|
timeout=1,
|
||||||
|
otp_sent_at=2000,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert code == "654321"
|
||||||
|
|||||||
Reference in New Issue
Block a user