mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-04 02:31:27 +00:00
fix(auth): reject unchanged password on /user/password/change
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
7c8aed072f
commit
28f70c75d1
2 changed files with 37 additions and 5 deletions
|
|
@ -63,11 +63,12 @@ async def change_password(
|
|||
"""
|
||||
Change the calling user's own password.
|
||||
|
||||
Requires the current password. The new password must satisfy the
|
||||
configured password policy (`general_settings.password_policy_*`: minimum
|
||||
length, character classes, and, when enabled, breached-password screening
|
||||
via haveibeenpwned.com). A successful change lifts any pending forced
|
||||
password reset (`password_reset_required`) on the account.
|
||||
Requires the current password. The new password must differ from the
|
||||
current one and satisfy the configured password policy
|
||||
(`general_settings.password_policy_*`: minimum length, character classes,
|
||||
and, when enabled, breached-password screening via haveibeenpwned.com).
|
||||
A successful change lifts any pending forced password reset
|
||||
(`password_reset_required`) on the account.
|
||||
|
||||
Parameters:
|
||||
- current_password: str - The user's current password.
|
||||
|
|
@ -103,6 +104,12 @@ async def change_password(
|
|||
if not verify_password(data.current_password, stored_password):
|
||||
raise HTTPException(status_code=400, detail=_error_detail("Current password is incorrect."))
|
||||
|
||||
if data.new_password == data.current_password:
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=_error_detail("New password must be different from the current password."),
|
||||
)
|
||||
|
||||
validate_password_policy(data.new_password, general_settings)
|
||||
await validate_password_not_breached(data.new_password, general_settings)
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,31 @@ async def test_change_password_rejects_wrong_current_password():
|
|||
prisma.db.litellm_usertable.update.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_change_password_rejects_unchanged_password():
|
||||
from litellm.proxy._types import ChangePasswordRequest
|
||||
|
||||
prisma = _make_prisma(_make_user_row(hash_password(CURRENT_PASSWORD)))
|
||||
|
||||
with (
|
||||
patch( # test-quality-ok: change_password reads proxy_server module globals; no injection seam
|
||||
"litellm.proxy.proxy_server.prisma_client", prisma
|
||||
),
|
||||
patch( # test-quality-ok: change_password reads proxy_server module globals; no injection seam
|
||||
"litellm.proxy.proxy_server.general_settings", _POLICY_NO_BREACH_CHECK
|
||||
),
|
||||
):
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
await change_password(
|
||||
data=ChangePasswordRequest(current_password=CURRENT_PASSWORD, new_password=CURRENT_PASSWORD),
|
||||
user_api_key_dict=_caller(),
|
||||
)
|
||||
|
||||
assert exc_info.value.status_code == 400
|
||||
assert "must be different from the current password" in exc_info.value.detail["error"]
|
||||
prisma.db.litellm_usertable.update.assert_not_called()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_change_password_rejects_session_without_user():
|
||||
from litellm.proxy._types import ChangePasswordRequest
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue