diff options
author | Sebastian <sebasjm@gmail.com> | 2024-01-23 18:00:42 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2024-01-24 17:14:02 -0300 |
commit | 236d4347f5884bb1d9ca1d3bb4ad0ba776577fd2 (patch) | |
tree | a38823a73006c38bd54cb438da81f13bb513dce5 /packages/demobank-ui/src/pages/RegistrationPage.tsx | |
parent | 579128ce40c7e56f390cadaf2fc2fd4cc6290d68 (diff) | |
download | wallet-core-236d4347f5884bb1d9ca1d3bb4ad0ba776577fd2.tar.xz |
many changes
activate eslint
update file headers
removed history and preact-router
remove eslint errors and more applied prettier
Diffstat (limited to 'packages/demobank-ui/src/pages/RegistrationPage.tsx')
-rw-r--r-- | packages/demobank-ui/src/pages/RegistrationPage.tsx | 257 |
1 files changed, 135 insertions, 122 deletions
diff --git a/packages/demobank-ui/src/pages/RegistrationPage.tsx b/packages/demobank-ui/src/pages/RegistrationPage.tsx index b3a49a178..931a9b700 100644 --- a/packages/demobank-ui/src/pages/RegistrationPage.tsx +++ b/packages/demobank-ui/src/pages/RegistrationPage.tsx @@ -13,29 +13,33 @@ 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 { AccessToken, HttpStatusCode, Logger, TalerErrorCode, TranslatedString } from "@gnu-taler/taler-util"; +import { + AccessToken, + HttpStatusCode, + TalerErrorCode, + TranslatedString, + assertUnreachable, +} from "@gnu-taler/taler-util"; import { LocalNotificationBanner, ShowInputErrorLabel, useLocalNotification, - useTranslationContext + useTranslationContext, } from "@gnu-taler/web-util/browser"; import { Fragment, VNode, h } from "preact"; import { useState } from "preact/hooks"; import { useBankCoreApiContext } from "../context/config.js"; -import { useBackendState } from "../hooks/backend.js"; +import { useSettingsContext } from "../context/settings.js"; +import { RouteDefinition } from "../route.js"; import { undefinedIfEmpty } from "../utils.js"; import { getRandomPassword, getRandomUsername } from "./rnd.js"; -import { useSettingsContext } from "../context/settings.js"; - -const logger = new Logger("RegistrationPage"); export function RegistrationPage({ - onComplete, - onCancel + onRegistrationSuccesful, + routeCancel, }: { - onComplete: () => void; - onCancel: () => void; + onRegistrationSuccesful: (user: string, password: string) => void; + routeCancel: RouteDefinition<Record<string, never>>; }): VNode { const { i18n } = useTranslationContext(); const { config } = useBankCoreApiContext(); @@ -44,50 +48,58 @@ export function RegistrationPage({ <p>{i18n.str`Currently, the bank is not accepting new registrations!`}</p> ); } - return <RegistrationForm onComplete={onComplete} onCancel={onCancel} />; + return ( + <RegistrationForm + onRegistrationSuccesful={onRegistrationSuccesful} + routeCancel={routeCancel} + /> + ); } export const USERNAME_REGEX = /^[a-z][a-zA-Z0-9-]*$/; export const PHONE_REGEX = /^(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}$/; -export const EMAIL_REGEX = /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/; +export const EMAIL_REGEX = /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/; -/** +/** * Collect and submit registration data. */ -function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, onCancel: () => void }): VNode { - const backend = useBackendState(); +function RegistrationForm({ + onRegistrationSuccesful, + routeCancel, +}: { + onRegistrationSuccesful: (user: string, password: string) => void; + routeCancel: RouteDefinition<Record<string, never>>; +}): VNode { const [username, setUsername] = useState<string | undefined>(); const [name, setName] = useState<string | undefined>(); const [password, setPassword] = useState<string | undefined>(); - const [phone, setPhone] = useState<string | undefined>(); - const [email, setEmail] = useState<string | undefined>(); + // const [phone, setPhone] = useState<string | undefined>(); + // const [email, setEmail] = useState<string | undefined>(); const [repeatPassword, setRepeatPassword] = useState<string | undefined>(); - const [notification, notify, handleError] = useLocalNotification() + const [notification, notify, handleError] = useLocalNotification(); const settings = useSettingsContext(); - const { api } = useBankCoreApiContext() + const { api } = useBankCoreApiContext(); // const { register } = useTestingAPI(); const { i18n } = useTranslationContext(); const errors = undefinedIfEmpty({ - name: !name - ? i18n.str`Missing name` - : undefined, + name: !name ? i18n.str`Missing name` : undefined, username: !username ? i18n.str`Missing username` : !USERNAME_REGEX.test(username) ? i18n.str`Use letters and numbers only, and start with a lowercase letter` : undefined, - phone: !phone - ? undefined - : !PHONE_REGEX.test(phone) - ? i18n.str`Use letters and numbers only, and start with a lowercase letter` - : undefined, - email: !email - ? undefined - : !EMAIL_REGEX.test(email) - ? i18n.str`Use letters and numbers only, and start with a lowercase letter` - : undefined, + // phone: !phone + // ? undefined + // : !PHONE_REGEX.test(phone) + // ? i18n.str`Use letters and numbers only, and start with a lowercase letter` + // : undefined, + // email: !email + // ? undefined + // : !EMAIL_REGEX.test(email) + // ? i18n.str`Use letters and numbers only, and start with a lowercase letter` + // : undefined, password: !password ? i18n.str`Missing password` : undefined, repeatPassword: !repeatPassword ? i18n.str`Missing password` @@ -96,106 +108,97 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on : undefined, }); - async function doRegistrationAndLogin(name: string, username: string, password: string, onComplete: () => void) { + async function doRegistrationAndLogin( + name: string, + username: string, + password: string, + onComplete: () => void, + ) { await handleError(async () => { - createAccount: { - const resp = await api.createAccount("" as AccessToken, { name, username, password }); - if (resp.type === "fail") { - switch (resp.case) { - case HttpStatusCode.BadRequest: return notify({ + const resp = await api.createAccount("" as AccessToken, { + name, + username, + password, + }); + if (resp.type === "ok") { + onComplete(); + } else { + switch (resp.case) { + case HttpStatusCode.BadRequest: + return notify({ type: "error", title: i18n.str`Server replied with invalid phone or email.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_UNALLOWED_DEBIT: return notify({ + }); + case TalerErrorCode.BANK_UNALLOWED_DEBIT: + return notify({ type: "error", title: i18n.str`Registration is disabled because the bank ran out of bonus credit.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case HttpStatusCode.Unauthorized: return notify({ + }); + case HttpStatusCode.Unauthorized: + return notify({ type: "error", title: i18n.str`No enough permission to create that account.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: return notify({ + }); + case TalerErrorCode.BANK_REGISTER_PAYTO_URI_REUSE: + return notify({ type: "error", title: i18n.str`That account id is already taken.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: return notify({ + }); + case TalerErrorCode.BANK_REGISTER_USERNAME_REUSE: + return notify({ type: "error", title: i18n.str`That username is already taken.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: return notify({ + }); + case TalerErrorCode.BANK_RESERVED_USERNAME_CONFLICT: + return notify({ type: "error", title: i18n.str`That username can't be used because is reserved.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: return notify({ + }); + case TalerErrorCode.BANK_NON_ADMIN_PATCH_DEBT_LIMIT: + return notify({ type: "error", title: i18n.str`Only admin is allow to set debt limit.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_MISSING_TAN_INFO: return notify({ + }); + case TalerErrorCode.BANK_MISSING_TAN_INFO: + return notify({ type: "error", title: i18n.str`No information for the selected authentication channel.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED: return notify({ + }); + case TalerErrorCode.BANK_TAN_CHANNEL_NOT_SUPPORTED: + return notify({ type: "error", title: i18n.str`Authentication channel is not supported.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL: return notify({ + }); + case TalerErrorCode.BANK_NON_ADMIN_SET_TAN_CHANNEL: + return notify({ type: "error", title: i18n.str`Only admin can create accounts with second factor authentication.`, description: resp.detail.hint as TranslatedString, debug: resp.detail, - }) - default: assertUnreachable(resp) - } - } - } - login: { - const resp = await api.getAuthenticationAPI(username).createAccessToken(password, { - scope: "readwrite", - duration: { d_us: "forever" }, - refreshable: true, - }) - - if (resp.type === "ok") { - backend.logIn({ username, token: resp.body.access_token }); - } else { - switch (resp.case) { - case HttpStatusCode.Unauthorized: return notify({ - type: "error", - title: i18n.str`Wrong credentials for "${username}"`, - description: resp.detail.hint as TranslatedString, - debug: resp.detail, - }) - case HttpStatusCode.NotFound: return notify({ - type: "error", - title: i18n.str`Account not found`, - description: resp.detail.hint as TranslatedString, - debug: resp.detail, - }) - default: assertUnreachable(resp) - } + }); + default: + assertUnreachable(resp); } - } - onComplete() - }) + }); } async function doRegistrationStep() { @@ -204,18 +207,21 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on setUsername(undefined); setPassword(undefined); setRepeatPassword(undefined); - onComplete(); - }) + onRegistrationSuccesful(username, password); + }); } - async function doRandomRegistration(tries: number = 3) { + async function doRandomRegistration() { const user = getRandomUsername(); - const pass = settings.simplePasswordForRandomAccounts ? "123" : getRandomPassword(); - const username = `_${user.first}-${user.second}_` - const name = `${user.first}, ${user.second}` - await doRegistrationAndLogin(name, username, pass, onComplete) - + const password = settings.simplePasswordForRandomAccounts + ? "123" + : getRandomPassword(); + const username = `_${user.first}-${user.second}_`; + const name = `${user.first}, ${user.second}`; + await doRegistrationAndLogin(name, username, password, () => { + onRegistrationSuccesful(username, password); + }); } return ( @@ -228,7 +234,9 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on </div> <div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm"> - <form class="space-y-6" noValidate + <form + class="space-y-6" + noValidate onSubmit={(e) => { e.preventDefault(); }} @@ -236,7 +244,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on autoCorrect="off" > <div> - <label for="username" class="block text-sm font-medium leading-6 text-gray-900"> + <label + for="username" + class="block text-sm font-medium leading-6 text-gray-900" + > <i18n.Translate>Username</i18n.Translate> <b style={{ color: "red" }}> *</b> </label> @@ -265,7 +276,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on <div> <div class="flex items-center justify-between"> - <label for="password" class="block text-sm font-medium leading-6 text-gray-900"> + <label + for="password" + class="block text-sm font-medium leading-6 text-gray-900" + > <i18n.Translate>Password</i18n.Translate> <b style={{ color: "red" }}> *</b> </label> @@ -294,7 +308,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on <div> <div class="flex items-center justify-between"> - <label for="register-repeat" class="block text-sm font-medium leading-6 text-gray-900"> + <label + for="register-repeat" + class="block text-sm font-medium leading-6 text-gray-900" + > <i18n.Translate>Repeat password</i18n.Translate> <b style={{ color: "red" }}> *</b> </label> @@ -323,7 +340,10 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on <div> <div class="flex items-center justify-between"> - <label for="name" class="block text-sm font-medium leading-6 text-gray-900"> + <label + for="name" + class="block text-sm font-medium leading-6 text-gray-900" + > <i18n.Translate>Name</i18n.Translate> <b style={{ color: "red" }}> *</b> </label> @@ -403,50 +423,43 @@ function RegistrationForm({ onComplete, onCancel }: { onComplete: () => void, on </div> */} <div class="flex w-full justify-between"> - <button type="submit" + <a + href={routeCancel.url({})} class="ring-1 ring-gray-600 rounded-md bg-white disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 text-black shadow-sm hover:bg-white-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" - onClick={(e) => { - e.preventDefault() - onCancel() - }} > <i18n.Translate>Cancel</i18n.Translate> - </button> - <button type="submit" + </a> + <button + type="submit" class=" rounded-md bg-indigo-600 disabled:bg-gray-300 px-3 py-1.5 text-sm font-semibold leading-6 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={async (e) => { - e.preventDefault() + e.preventDefault(); - doRegistrationStep() + doRegistrationStep(); }} > <i18n.Translate>Register</i18n.Translate> </button> </div> - </form> - {settings.allowRandomAccountCreation && + {settings.allowRandomAccountCreation && ( <p class="mt-10 text-center text-sm text-gray-500 border-t"> - <button type="submit" + <button + type="submit" class="flex mt-4 w-full justify-center rounded-md bg-green-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-green-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-green-600" onClick={(e) => { - e.preventDefault() - doRandomRegistration() + e.preventDefault(); + doRandomRegistration(); }} > <i18n.Translate>Create a random temporary user</i18n.Translate> </button> </p> - } + )} </div> </div> - </Fragment> ); } - -export function assertUnreachable(x: never): never { - throw new Error("Didn't expect to get here"); -} |