keep the login code when Kavenegar answers late instead of failing the request
Seen live on 2026-09-27: Kavenegar took 5.4 s, our 5 s timeout fired, the API answered 503 and deleted the code, but the SMS arrived, so the site said "service unavailable" while the phone held a code that no longer worked. A read timeout now means "delivery unknown": the code is kept and the request succeeds (the cooldown still blocks a second SMS). A failed connection is still an explicit 503. Read timeout raised to 10 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -164,3 +164,33 @@ class VerifyLookupTests(TestCase):
|
||||
with patch('accounts.services.requests.post', return_value=_kavenegar_reply(424, 424)):
|
||||
self.assertEqual(_request('09121113303').status_code, 503)
|
||||
self.assertFalse(OTPCode.objects.filter(phone='09121113303').exists())
|
||||
|
||||
|
||||
@override_settings(DEBUG=False, KAVENEGAR_API_KEY='k', KAVENEGAR_OTP_TEMPLATE='SMSVerify', TEST_LOGIN_PHONES={})
|
||||
class SlowProviderTests(TestCase):
|
||||
"""۲۰۲۶-۰۹-۲۷: کاوهنگار ۵٫۴ ثانیه طول کشید، پیامک رسید، ولی ما ۵۰۳ دادیم و کد را پاک کردیم."""
|
||||
|
||||
def setUp(self):
|
||||
cache.clear()
|
||||
|
||||
def test_late_reply_keeps_the_code_and_moves_the_user_on(self):
|
||||
with patch('accounts.views.secrets.randbelow', return_value=135790), \
|
||||
patch('accounts.services.requests.post', side_effect=requests.ReadTimeout('slow')):
|
||||
self.assertEqual(_request('09121114401').status_code, 200)
|
||||
self.assertTrue(OTPCode.objects.filter(phone='09121114401', code='135790', is_used=False).exists())
|
||||
login = APIClient().post('/api/auth/login', {'phone': '09121114401', 'otp': '135790'}, format='json')
|
||||
self.assertEqual(login.status_code, 200)
|
||||
# cooldown سرِ جایش است، پس دکمهی دوباره پیامکِ دوم نمیفرستد
|
||||
with patch('accounts.services.requests.post') as post:
|
||||
self.assertEqual(_request('09121114401').status_code, 429)
|
||||
post.assert_not_called()
|
||||
|
||||
def test_no_connection_is_still_an_explicit_503(self):
|
||||
with patch('accounts.services.requests.post', side_effect=requests.ConnectTimeout('down')):
|
||||
self.assertEqual(_request('09121114402').status_code, 503)
|
||||
self.assertFalse(OTPCode.objects.filter(phone='09121114402').exists())
|
||||
|
||||
def test_read_timeout_is_ten_seconds(self):
|
||||
with patch('accounts.services.requests.post', return_value=_kavenegar_reply()) as post:
|
||||
_request('09121114403')
|
||||
self.assertEqual(post.call_args.kwargs['timeout'], (3.05, 10))
|
||||
|
||||
Reference in New Issue
Block a user