/* This file is part of GNU Taler (C) 2022 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 */ import { Logger } from "@gnu-taler/taler-util"; import { Fragment, h, VNode } from "preact"; import { route } from "preact-router"; import { StateUpdater, useState } from "preact/hooks"; import { useBackendContext } from "../context/backend.js"; import { PageStateType, usePageContext } from "../context/pageState.js"; import { InternationalizationAPI, useTranslationContext, } from "@gnu-taler/web-util/lib/index.browser"; import { BackendStateHandler } from "../hooks/backend.js"; import { bankUiSettings } from "../settings.js"; import { getBankBackendBaseUrl, undefinedIfEmpty } from "../utils.js"; import { BankFrame } from "./BankFrame.js"; import { ShowInputErrorLabel } from "./ShowInputErrorLabel.js"; const logger = new Logger("RegistrationPage"); export function RegistrationPage(): VNode { const { i18n } = useTranslationContext(); if (!bankUiSettings.allowRegistrations) { return (

{i18n.str`Currently, the bank is not accepting new registrations!`}

); } return ( ); } const usernameRegex = /^[a-z][a-zA-Z0-9]+$/; /** * Collect and submit registration data. */ function RegistrationForm(): VNode { const backend = useBackendContext(); const { pageState, pageStateSetter } = usePageContext(); const [username, setUsername] = useState(); const [password, setPassword] = useState(); const [repeatPassword, setRepeatPassword] = useState(); const { i18n } = useTranslationContext(); const errors = undefinedIfEmpty({ username: !username ? i18n.str`Missing username` : !usernameRegex.test(username) ? i18n.str`Use only letter and numbers starting with a lower case letter` : undefined, password: !password ? i18n.str`Missing password` : !usernameRegex.test(password) ? i18n.str`Use only letter and numbers starting with a lower case letter` : undefined, repeatPassword: !repeatPassword ? i18n.str`Missing password` : repeatPassword !== password ? i18n.str`Password don't match` : undefined, }); return (

{i18n.str`Welcome to ${bankUiSettings.bankName}!`}

{i18n.str`Please register!`}

{ setUsername(e.currentTarget.value); }} />

{ setPassword(e.currentTarget.value); }} />

{ setRepeatPassword(e.currentTarget.value); }} />
{/* FIXME: should use a different color */}
); } /** * This function requests /register. * * This function is responsible to change two states: * the backend's (to store the login credentials) and * the page's (to indicate a successful login or a problem). */ async function registrationCall( req: { username: string; password: string }, /** * FIXME: figure out if the two following * functions can be retrieved somewhat from * the state. */ backend: BackendStateHandler, pageStateSetter: StateUpdater, i18n: InternationalizationAPI, ): Promise { const url = getBankBackendBaseUrl(); const headers = new Headers(); headers.append("Content-Type", "application/json"); const registerEndpoint = new URL("access-api/testing/register", url); let res: Response; try { res = await fetch(registerEndpoint.href, { method: "POST", body: JSON.stringify({ username: req.username, password: req.password, }), headers, }); } catch (error) { logger.error( `Could not POST new registration to the bank (${registerEndpoint.href})`, error, ); pageStateSetter((prevState) => ({ ...prevState, error: { title: i18n.str`Registration failed, please report`, debug: JSON.stringify(error), }, })); return; } if (!res.ok) { const response = await res.json(); if (res.status === 409) { pageStateSetter((prevState) => ({ ...prevState, error: { title: i18n.str`That username is already taken`, debug: JSON.stringify(response), }, })); } else { pageStateSetter((prevState) => ({ ...prevState, error: { title: i18n.str`New registration gave response error`, debug: JSON.stringify(response), }, })); } } else { // registration was ok backend.save({ url, username: req.username, password: req.password, }); route("/account"); } }