Skip to content

Commit 13a71fd

Browse files
committed
Add error message on change password mismatch
1 parent 4e6f3fd commit 13a71fd

File tree

5 files changed

+47
-12
lines changed

5 files changed

+47
-12
lines changed

futuramaapi/routers/services/passwords/change_signature_requested_user_password.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from typing import Any, ClassVar
22

33
import jwt
4-
from fastapi import HTTPException, Request, status
4+
from fastapi import Request, status
55
from fastapi.responses import RedirectResponse
66
from jwt import ExpiredSignatureError, InvalidSignatureError, InvalidTokenError
77
from pydantic import SecretStr
@@ -11,6 +11,8 @@
1111
from futuramaapi.repositories.models import UserModel
1212
from futuramaapi.routers.services import BaseSessionService
1313

14+
from .get_signature_user_password_change_form import ChangeFormError
15+
1416

1517
class TokenDecodeError(Exception):
1618
pass
@@ -56,14 +58,14 @@ async def process(self, *args, **kwargs) -> RedirectResponse:
5658
try:
5759
token_: dict[str, Any] = self._get_decoded_token()
5860
except TokenDecodeError:
59-
raise HTTPException(
60-
status_code=status.HTTP_401_UNAUTHORIZED,
61-
detail="Token expired or invalid.",
62-
) from None
61+
return RedirectResponse(
62+
url=f"/passwords/change?sig={self.signature}",
63+
status_code=status.HTTP_303_SEE_OTHER,
64+
)
6365

6466
if self.password1.get_secret_value() != self.password2.get_secret_value():
6567
return RedirectResponse(
66-
self.request.headers.get("referer", self.request.url.path),
68+
url=f"/passwords/change?sig={self.signature}&errorType={ChangeFormError.password_mismatch}",
6769
status_code=status.HTTP_303_SEE_OTHER,
6870
)
6971

futuramaapi/routers/services/passwords/get_signature_user_password_change_form.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from enum import StrEnum
12
from typing import Any, ClassVar
23

34
import jwt
@@ -16,10 +17,15 @@ class TokenDecodeError(Exception):
1617
pass
1718

1819

20+
class ChangeFormError(StrEnum):
21+
password_mismatch = "password_mismatch" # noqa: S105
22+
23+
1924
class GetSignatureUserPasswordChangeFormService(BaseSessionService[Response]):
2025
template_name: ClassVar[str] = "password_change.html"
2126

2227
signature: str
28+
error_type: ChangeFormError | None
2329

2430
algorithm: ClassVar[str] = "HS256"
2531

@@ -59,6 +65,7 @@ async def _get_context(self, token: dict[str, Any], /) -> dict[str, Any]:
5965
return {
6066
"_project": _project_context,
6167
"current_user": await self._get_current_user(token["user"]["id"]),
68+
"error_type": self.error_type,
6269
}
6370

6471
async def process(self, *args, **kwargs) -> Response:

futuramaapi/routers/views/passwords/api.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
ChangeSignatureRequestedUserPasswordService,
1010
)
1111
from futuramaapi.routers.services.passwords.get_signature_user_password_change_form import (
12+
ChangeFormError,
1213
GetSignatureUserPasswordChangeFormService,
1314
)
1415

@@ -30,11 +31,21 @@
3031
)
3132
async def get_signature_user_password_change_form(
3233
request: Request,
33-
sig: str,
34+
sig: Annotated[
35+
str,
36+
Query(),
37+
],
38+
error_type: Annotated[
39+
ChangeFormError | None,
40+
Query(
41+
alias="errorType",
42+
),
43+
] = None,
3444
) -> Response:
3545
"""Show password change form."""
3646
service: GetSignatureUserPasswordChangeFormService = GetSignatureUserPasswordChangeFormService(
3747
signature=sig,
48+
error_type=error_type,
3849
context={
3950
"request": request,
4051
},

static/css/auth.css

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,25 @@
77
padding-bottom: 2rem;
88
}
99

10-
.auth-warning {
10+
.auth-message {
1111
margin-top: 1.25rem;
1212
padding: 0.6rem 0.75rem;
1313
border-radius: 0.6rem;
14-
background: rgba(234, 179, 8, 0.12); /* amber */
15-
color: #92400e;
1614
font-size: 0.8rem;
1715
text-align: center;
1816
line-height: 1.4;
1917
}
2018

19+
.auth-message.warning {
20+
background: rgba(234, 179, 8, 0.12);
21+
color: #92400e;
22+
}
23+
24+
.auth-message.error {
25+
background: rgba(220, 38, 38, 0.12);
26+
color: #b91c1c;
27+
}
28+
2129
.auth-container {
2230
width: 100%;
2331
max-width: 380px;

templates/password_change.html

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,13 @@
2929
Reset password
3030
</h1>
3131
{% if current_user %}
32+
{% if error_type == 'password_mismatch' %}
33+
<p
34+
class="auth-message error"
35+
>
36+
Passwords do not match.
37+
</p>
38+
{% endif %}
3239
<p
3340
class="auth-subtitle"
3441
>
@@ -83,7 +90,7 @@
8390
</button>
8491
</form>
8592
<p
86-
class="auth-warning"
93+
class="auth-message warning"
8794
>
8895
This reset link expires in <span id="reset-password-countdown">15:00</span>.
8996
</p>
@@ -94,7 +101,7 @@
94101
This password reset link has expired or is invalid.
95102
</p>
96103
<div
97-
class="auth-warning"
104+
class="auth-message warning"
98105
>
99106
Please request a new password reset link via API.
100107
</div>

0 commit comments

Comments
 (0)