Skip to content

Commit df5c9df

Browse files
committed
fix: align auth reset password token API
1 parent ffc85d9 commit df5c9df

3 files changed

Lines changed: 46 additions & 4 deletions

File tree

insforge/auth/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,9 @@ async def reset_password(
255255
self,
256256
*,
257257
new_password: str,
258-
otp: str,
258+
token: str,
259259
) -> AuthEmailActionResponse:
260-
payload = AuthResetPasswordRequest(new_password=new_password, otp=otp).model_dump(
260+
payload = AuthResetPasswordRequest(new_password=new_password, token=token).model_dump(
261261
by_alias=True,
262262
exclude_none=True,
263263
)

insforge/auth/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class AuthResetPasswordRequest(BaseModel):
5252
model_config = ConfigDict(extra="ignore", populate_by_name=True)
5353

5454
new_password: str = Field(alias="newPassword")
55-
otp: str
55+
token: str = Field(alias="otp")
5656

5757

5858
class CurrentProfileResponse(BaseModel):

tests/auth/test_auth_client.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ async def fake_request(method: str, url: httpx.URL, **kwargs: object) -> httpx.R
482482
)
483483
reset = await client.auth.reset_password(
484484
new_password="new-password",
485-
otp="reset-token",
485+
token="reset-token",
486486
)
487487

488488
return calls, send_verification, verify, send_reset, exchange, reset
@@ -540,3 +540,45 @@ async def fake_request(method: str, url: httpx.URL, **kwargs: object) -> httpx.R
540540
assert exchange.expires_at.isoformat() == "2026-03-28T12:34:56+00:00"
541541

542542
assert reset.message == "Password reset successfully"
543+
544+
545+
def test_auth_email_json_endpoints_omit_optional_redirect_and_raise_auth_errors() -> None:
546+
async def scenario() -> tuple[dict[str, object], dict[str, object]]:
547+
captured_send: dict[str, object] = {}
548+
captured_verify: dict[str, object] = {}
549+
550+
async def fake_request(method: str, url: httpx.URL, **kwargs: object) -> httpx.Response:
551+
if str(url).endswith("/api/auth/email/send-verification"):
552+
captured_send["method"] = method
553+
captured_send["url"] = str(url)
554+
captured_send["kwargs"] = kwargs
555+
return httpx.Response(202, json={"success": True, "message": "Verification email sent"})
556+
557+
captured_verify["method"] = method
558+
captured_verify["url"] = str(url)
559+
captured_verify["kwargs"] = kwargs
560+
return httpx.Response(401, json={"error": "INVALID_OTP", "message": "Verification code expired"})
561+
562+
async with InsforgeClient(
563+
base_url="https://example.com",
564+
api_key="ins_test",
565+
) as client:
566+
client.http_client.request = fake_request # type: ignore[method-assign]
567+
response = await client.auth.send_email_verification(email="a@example.com")
568+
assert response.success is True
569+
570+
try:
571+
await client.auth.verify_email(email="a@example.com", otp="123456")
572+
except InsforgeAuthError as exc:
573+
assert exc.error == "INVALID_OTP"
574+
assert exc.message == "Verification code expired"
575+
else:
576+
raise AssertionError("verify_email should raise InsforgeAuthError on 401")
577+
578+
return captured_send, captured_verify
579+
580+
captured_send, captured_verify = asyncio.run(scenario())
581+
582+
assert captured_send["kwargs"]["json"] == {"email": "a@example.com"}
583+
assert "Authorization" not in captured_send["kwargs"]["headers"]
584+
assert captured_verify["kwargs"]["params"] == {"client_type": "server"}

0 commit comments

Comments
 (0)