aboutsummaryrefslogtreecommitdiff
path: root/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx')
-rw-r--r--packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx173
1 files changed, 105 insertions, 68 deletions
diff --git a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
index 32e100e43..3b35c1fe1 100644
--- a/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
+++ b/packages/demobank-ui/src/pages/account/UpdateAccountPassword.tsx
@@ -1,45 +1,76 @@
-import { notifyInfo, useLocalNotification, useTranslationContext } from "@gnu-taler/web-util/browser";
+/*
+ This file is part of GNU Taler
+ (C) 2022-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+ AbsoluteTime,
+ HttpStatusCode,
+ TalerErrorCode,
+ assertUnreachable,
+} from "@gnu-taler/taler-util";
+import {
+ LocalNotificationBanner,
+ ShowInputErrorLabel,
+ notifyInfo,
+ useLocalNotification,
+ useTranslationContext,
+} from "@gnu-taler/web-util/browser";
import { Fragment, VNode, h } from "preact";
import { useState } from "preact/hooks";
-import { ShowInputErrorLabel } from "@gnu-taler/web-util/browser";
import { useBankCoreApiContext } from "../../context/config.js";
import { useBackendState } from "../../hooks/backend.js";
-import { undefinedIfEmpty, withRuntimeErrorHandling } from "../../utils.js";
+import { useBankState } from "../../hooks/bank-state.js";
+import { RouteDefinition } from "../../route.js";
+import { undefinedIfEmpty } from "../../utils.js";
import { doAutoFocus } from "../PaytoWireTransferForm.js";
import { ProfileNavigation } from "../ProfileNavigation.js";
-import { assertUnreachable } from "../WithdrawalOperationPage.js";
-import { LocalNotificationBanner } from "@gnu-taler/web-util/browser";
-import { AbsoluteTime, HttpStatusCode, TalerErrorCode } from "@gnu-taler/taler-util";
-import { useBankState } from "../../hooks/bank-state.js";
export function UpdateAccountPassword({
account: accountName,
- onCancel,
+ routeClose,
onUpdateSuccess,
onAuthorizationRequired,
focus,
}: {
- onCancel: () => void;
- focus?: boolean,
- onAuthorizationRequired: () => void,
+ routeClose: RouteDefinition<Record<string, never>>;
+ focus?: boolean;
+ onAuthorizationRequired: () => void;
onUpdateSuccess: () => void;
account: string;
}): VNode {
const { i18n } = useTranslationContext();
const { state: credentials } = useBackendState();
- const token = credentials.status !== "loggedIn" ? undefined : credentials.token
+ const token =
+ credentials.status !== "loggedIn" ? undefined : credentials.token;
const { api } = useBankCoreApiContext();
const [current, setCurrent] = useState<string | undefined>();
const [password, setPassword] = useState<string | undefined>();
const [repeat, setRepeat] = useState<string | undefined>();
- const [, updateBankState] = useBankState()
+ const [, updateBankState] = useBankState();
- const accountIsTheCurrentUser = credentials.status === "loggedIn" ?
- credentials.username === accountName : false
+ const accountIsTheCurrentUser =
+ credentials.status === "loggedIn"
+ ? credentials.username === accountName
+ : false;
const errors = undefinedIfEmpty({
- current: !accountIsTheCurrentUser ? undefined : !current ? i18n.str`required` : undefined,
+ current: !accountIsTheCurrentUser
+ ? undefined
+ : !current
+ ? i18n.str`required`
+ : undefined,
password: !password ? i18n.str`required` : undefined,
repeat: !repeat
? i18n.str`required`
@@ -47,8 +78,7 @@ export function UpdateAccountPassword({
? i18n.str`password doesn't match`
: undefined,
});
- const [notification, notify, handleError] = useLocalNotification()
-
+ const [notification, notify, handleError] = useLocalNotification();
async function doChangePassword() {
if (!!errors || !password || !token) return;
@@ -56,54 +86,62 @@ export function UpdateAccountPassword({
const request = {
old_password: current,
new_password: password,
- }
- const resp = await api.updatePassword({ username: accountName, token }, request);
+ };
+ const resp = await api.updatePassword(
+ { username: accountName, token },
+ request,
+ );
if (resp.type === "ok") {
notifyInfo(i18n.str`Password changed`);
onUpdateSuccess();
} else {
switch (resp.case) {
- case HttpStatusCode.Unauthorized: return notify({
- type: "error",
- title: i18n.str`Not authorized to change the password, maybe the session is invalid.`
- })
- case HttpStatusCode.NotFound: return notify({
- type: "error",
- title: i18n.str`Account not found`
- })
- case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD: return notify({
- type: "error",
- title: i18n.str`You need to provide the old password. If you don't have it contact your account administrator.`
- })
- case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD: return notify({
- type: "error",
- title: i18n.str`Your current password doesn't match, can't change to a new password.`
- })
+ case HttpStatusCode.Unauthorized:
+ return notify({
+ type: "error",
+ title: i18n.str`Not authorized to change the password, maybe the session is invalid.`,
+ });
+ case HttpStatusCode.NotFound:
+ return notify({
+ type: "error",
+ title: i18n.str`Account not found`,
+ });
+ case TalerErrorCode.BANK_NON_ADMIN_PATCH_MISSING_OLD_PASSWORD:
+ return notify({
+ type: "error",
+ title: i18n.str`You need to provide the old password. If you don't have it contact your account administrator.`,
+ });
+ case TalerErrorCode.BANK_PATCH_BAD_OLD_PASSWORD:
+ return notify({
+ type: "error",
+ title: i18n.str`Your current password doesn't match, can't change to a new password.`,
+ });
case HttpStatusCode.Accepted: {
updateBankState("currentChallenge", {
operation: "update-password",
id: String(resp.body.challenge_id),
sent: AbsoluteTime.never(),
request,
- })
- return onAuthorizationRequired()
+ });
+ return onAuthorizationRequired();
}
- default: assertUnreachable(resp)
+ default:
+ assertUnreachable(resp);
}
}
- })
+ });
}
return (
<Fragment>
<LocalNotificationBanner notification={notification} />
- {accountIsTheCurrentUser ?
- <ProfileNavigation current="credentials" /> :
+ {accountIsTheCurrentUser ? (
+ <ProfileNavigation current="credentials" />
+ ) : (
<h1 class="text-base font-semibold leading-6 text-gray-900">
<i18n.Translate>Account "{accountName}"</i18n.Translate>
</h1>
-
- }
+ )}
<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
<div class="px-4 sm:px-0">
@@ -115,8 +153,8 @@ export function UpdateAccountPassword({
class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2"
autoCapitalize="none"
autoCorrect="off"
- onSubmit={e => {
- e.preventDefault()
+ onSubmit={(e) => {
+ e.preventDefault();
}}
>
<div class="px-4 py-6 sm:p-8">
@@ -138,7 +176,7 @@ export function UpdateAccountPassword({
data-error={!!errors?.password && password !== undefined}
value={password ?? ""}
onChange={(e) => {
- setPassword(e.currentTarget.value)
+ setPassword(e.currentTarget.value);
}}
autocomplete="off"
/>
@@ -165,7 +203,7 @@ export function UpdateAccountPassword({
data-error={!!errors?.repeat && repeat !== undefined}
value={repeat ?? ""}
onChange={(e) => {
- setRepeat(e.currentTarget.value)
+ setRepeat(e.currentTarget.value);
}}
// placeholder=""
autocomplete="off"
@@ -175,12 +213,12 @@ export function UpdateAccountPassword({
isDirty={repeat !== undefined}
/>
</div>
- <p class="mt-2 text-sm text-gray-500" >
+ <p class="mt-2 text-sm text-gray-500">
<i18n.Translate>repeat the same password</i18n.Translate>
</p>
</div>
- {accountIsTheCurrentUser ?
+ {accountIsTheCurrentUser ? (
<div class="sm:col-span-5">
<label
class="block text-sm font-medium leading-6 text-gray-900"
@@ -197,7 +235,7 @@ export function UpdateAccountPassword({
data-error={!!errors?.current && current !== undefined}
value={current ?? ""}
onChange={(e) => {
- setCurrent(e.currentTarget.value)
+ setCurrent(e.currentTarget.value);
}}
autocomplete="off"
/>
@@ -206,29 +244,29 @@ export function UpdateAccountPassword({
isDirty={current !== undefined}
/>
</div>
- <p class="mt-2 text-sm text-gray-500" >
- <i18n.Translate>your current password, for security</i18n.Translate>
+ <p class="mt-2 text-sm text-gray-500">
+ <i18n.Translate>
+ your current password, for security
+ </i18n.Translate>
</p>
</div>
- : undefined}
-
+ ) : undefined}
</div>
</div>
<div class="flex items-center justify-between gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
- {onCancel ?
- <button type="button" class="text-sm font-semibold leading-6 text-gray-900"
- onClick={onCancel}
- >
- <i18n.Translate>Cancel</i18n.Translate>
- </button>
- : <div />
- }
- <button type="submit"
+ <a
+ href={routeClose.url({})}
+ class="text-sm font-semibold leading-6 text-gray-900"
+ >
+ <i18n.Translate>Cancel</i18n.Translate>
+ </a>
+ <button
+ type="submit"
class="disabled:opacity-50 disabled:cursor-default cursor-pointer rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"
disabled={!!errors}
onClick={(e) => {
- e.preventDefault()
- doChangePassword()
+ e.preventDefault();
+ doChangePassword();
}}
>
<i18n.Translate>Change</i18n.Translate>
@@ -237,6 +275,5 @@ export function UpdateAccountPassword({
</form>
</div>
</Fragment>
-
);
-} \ No newline at end of file
+}