mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-18 10:15:41 +00:00
feat: register an account
This commit is contained in:
parent
b569083db6
commit
322ae444b2
91
assets/components/LoginForm.tsx
Normal file
91
assets/components/LoginForm.tsx
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import {Alert, Button, Form, Input, Space} from "antd";
|
||||||
|
import {t} from "ttag";
|
||||||
|
import React, {useContext, useEffect, useState} from "react";
|
||||||
|
import {getUser, login} from "../utils/api";
|
||||||
|
import {AuthenticatedContext} from "../pages/LoginPage";
|
||||||
|
import {useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
type FieldType = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LoginForm({ssoLogin}: { ssoLogin?: boolean }) {
|
||||||
|
|
||||||
|
const [error, setError] = useState<string>()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUser().then(() => {
|
||||||
|
setIsAuthenticated(true)
|
||||||
|
navigate('/home')
|
||||||
|
})
|
||||||
|
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
|
||||||
|
const onFinish = (data: FieldType) => {
|
||||||
|
login(data.username, data.password).then(() => {
|
||||||
|
setIsAuthenticated(true)
|
||||||
|
navigate('/home')
|
||||||
|
}).catch((e) => {
|
||||||
|
setIsAuthenticated(false)
|
||||||
|
if (e.response.data.message !== undefined) {
|
||||||
|
setError(e.response.data.message)
|
||||||
|
} else {
|
||||||
|
setError(e.response.data['hydra:description'])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return <>
|
||||||
|
{error &&
|
||||||
|
<Alert
|
||||||
|
type='error'
|
||||||
|
message={t`Error`}
|
||||||
|
banner={true}
|
||||||
|
role='role'
|
||||||
|
description={error}
|
||||||
|
style={{marginBottom: '1em'}}
|
||||||
|
/>}
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
labelCol={{span: 8}}
|
||||||
|
wrapperCol={{span: 16}}
|
||||||
|
style={{maxWidth: 600}}
|
||||||
|
onFinish={onFinish}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label={t`E-mail`}
|
||||||
|
name="username"
|
||||||
|
rules={[{required: true, message: t`Required`}]}
|
||||||
|
>
|
||||||
|
<Input autoFocus/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item<FieldType>
|
||||||
|
label={t`Password`}
|
||||||
|
name="password"
|
||||||
|
rules={[{required: true, message: t`Required`}]}
|
||||||
|
>
|
||||||
|
<Input.Password/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Space>
|
||||||
|
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||||
|
<Button type="primary" htmlType="submit">
|
||||||
|
{t`Submit`}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
{ssoLogin && <Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||||
|
<Button type="dashed" htmlType="button" href="/login/oauth">
|
||||||
|
{t`Log in with SSO`}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>}
|
||||||
|
</Space>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
}
|
||||||
70
assets/components/RegisterForm.tsx
Normal file
70
assets/components/RegisterForm.tsx
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import {Alert, Button, Form, Input} from "antd";
|
||||||
|
import {t} from "ttag";
|
||||||
|
import React, {useState} from "react";
|
||||||
|
import {register} from "../utils/api";
|
||||||
|
import {useNavigate} from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
type FieldType = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RegisterForm() {
|
||||||
|
|
||||||
|
const [error, setError] = useState<string>()
|
||||||
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const onFinish = (data: FieldType) => {
|
||||||
|
register(data.username, data.password).then(() => {
|
||||||
|
navigate('/home')
|
||||||
|
}).catch((e) => {
|
||||||
|
if (e.response.data.message !== undefined) {
|
||||||
|
setError(e.response.data.message)
|
||||||
|
} else {
|
||||||
|
setError(e.response.data['hydra:description'])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return <>
|
||||||
|
{error &&
|
||||||
|
<Alert
|
||||||
|
type='error'
|
||||||
|
message={t`Error`}
|
||||||
|
banner={true}
|
||||||
|
role='role'
|
||||||
|
description={error}
|
||||||
|
style={{marginBottom: '1em'}}
|
||||||
|
/>}
|
||||||
|
<Form
|
||||||
|
name="basic"
|
||||||
|
labelCol={{span: 8}}
|
||||||
|
wrapperCol={{span: 16}}
|
||||||
|
style={{maxWidth: 600}}
|
||||||
|
onFinish={onFinish}
|
||||||
|
autoComplete="off"
|
||||||
|
>
|
||||||
|
<Form.Item
|
||||||
|
label={t`E-mail`}
|
||||||
|
name="username"
|
||||||
|
rules={[{required: true, message: t`Required`}]}
|
||||||
|
>
|
||||||
|
<Input autoFocus/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item<FieldType>
|
||||||
|
label={t`Password`}
|
||||||
|
name="password"
|
||||||
|
rules={[{required: true, message: t`Required`}]}
|
||||||
|
>
|
||||||
|
<Input.Password/>
|
||||||
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
||||||
|
<Button block type="primary" htmlType="submit">
|
||||||
|
{t`Register`}
|
||||||
|
</Button>
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
}
|
||||||
@ -1,14 +1,11 @@
|
|||||||
import React, {createContext, useContext, useEffect, useState} from "react";
|
import React, {createContext, useEffect, useState} from "react";
|
||||||
import {Alert, Button, Card, Form, Input} from "antd";
|
import {Button, Card} from "antd";
|
||||||
import {getConfiguration, getUser, InstanceConfig, login} from "../utils/api";
|
|
||||||
import {useNavigate} from "react-router-dom";
|
|
||||||
import {t} from 'ttag'
|
import {t} from 'ttag'
|
||||||
import TextPage from "./TextPage";
|
import TextPage from "./TextPage";
|
||||||
|
import {LoginForm} from "../components/LoginForm";
|
||||||
|
import {getConfiguration, InstanceConfig} from "../utils/api";
|
||||||
|
import {RegisterForm} from "../components/RegisterForm";
|
||||||
|
|
||||||
type FieldType = {
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gridStyle: React.CSSProperties = {
|
const gridStyle: React.CSSProperties = {
|
||||||
width: '50%',
|
width: '50%',
|
||||||
@ -19,79 +16,27 @@ export const AuthenticatedContext = createContext<any>(null)
|
|||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
|
|
||||||
const [error, setError] = useState<string>()
|
const [wantRegister, setWantRegister] = useState<boolean>(false)
|
||||||
const [configuration, setConfiguration] = useState<InstanceConfig>()
|
const [configuration, setConfiguration] = useState<InstanceConfig>()
|
||||||
const navigate = useNavigate()
|
|
||||||
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
|
||||||
|
|
||||||
const onFinish = (data: FieldType) => {
|
const toggleWantRegister = () => {
|
||||||
login(data.username, data.password).then(() => {
|
setWantRegister(!wantRegister)
|
||||||
setIsAuthenticated(true)
|
|
||||||
navigate('/home')
|
|
||||||
}).catch((e) => {
|
|
||||||
setIsAuthenticated(false)
|
|
||||||
if (e.response.data.message !== undefined) {
|
|
||||||
setError(e.response.data.message)
|
|
||||||
} else {
|
|
||||||
setError(e.response.data['hydra:description'])
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getUser().then(() => {
|
|
||||||
setIsAuthenticated(true)
|
|
||||||
navigate('/home')
|
|
||||||
})
|
|
||||||
getConfiguration().then(setConfiguration)
|
getConfiguration().then(setConfiguration)
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
return <Card title={t`Log in`} style={{width: '100%'}}>
|
return <Card title={wantRegister ? t`Register` : t`Log in`} style={{width: '100%'}}>
|
||||||
<Card.Grid style={gridStyle} hoverable={false}>
|
<Card.Grid style={gridStyle} hoverable={false}>
|
||||||
{error &&
|
{wantRegister ? <RegisterForm/> : <LoginForm ssoLogin={configuration?.ssoLogin}/>}
|
||||||
<Alert
|
{
|
||||||
type='error'
|
configuration?.registerEnabled &&
|
||||||
message={t`Error`}
|
<Button type='link'
|
||||||
banner={true}
|
block
|
||||||
role='role'
|
style={{marginTop: '1em'}}
|
||||||
description={error}
|
onClick={toggleWantRegister}>{wantRegister ? 'Login' : 'Create an account'}</Button>
|
||||||
style={{marginBottom: '1em'}}
|
}
|
||||||
/>}
|
|
||||||
<Form
|
|
||||||
name="basic"
|
|
||||||
labelCol={{span: 8}}
|
|
||||||
wrapperCol={{span: 16}}
|
|
||||||
style={{maxWidth: 600}}
|
|
||||||
onFinish={onFinish}
|
|
||||||
autoComplete="off"
|
|
||||||
>
|
|
||||||
<Form.Item
|
|
||||||
label={t`Username`}
|
|
||||||
name="username"
|
|
||||||
rules={[{required: true, message: t`Required`}]}
|
|
||||||
>
|
|
||||||
<Input autoFocus/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item<FieldType>
|
|
||||||
label={t`Password`}
|
|
||||||
name="password"
|
|
||||||
rules={[{required: true, message: t`Required`}]}
|
|
||||||
>
|
|
||||||
<Input.Password/>
|
|
||||||
</Form.Item>
|
|
||||||
|
|
||||||
<Form.Item wrapperCol={{offset: 8, span: 16}}>
|
|
||||||
<Button block type="primary" htmlType="submit">
|
|
||||||
{t`Submit`}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>
|
|
||||||
{configuration?.ssoLogin && <Form.Item wrapperCol={{offset: 8, span: 16}}>
|
|
||||||
<Button type="dashed" htmlType="button" href="/login/oauth" block>
|
|
||||||
{t`Log in with SSO`}
|
|
||||||
</Button>
|
|
||||||
</Form.Item>}
|
|
||||||
</Form>
|
|
||||||
</Card.Grid>
|
</Card.Grid>
|
||||||
<Card.Grid style={gridStyle} hoverable={false}>
|
<Card.Grid style={gridStyle} hoverable={false}>
|
||||||
<TextPage resource='ads.md'/>
|
<TextPage resource='ads.md'/>
|
||||||
|
|||||||
@ -74,6 +74,7 @@ export interface Watchlist {
|
|||||||
export interface InstanceConfig {
|
export interface InstanceConfig {
|
||||||
ssoLogin: boolean
|
ssoLogin: boolean
|
||||||
limtedFeatures: boolean
|
limtedFeatures: boolean
|
||||||
|
registerEnabled: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig): Promise<R> {
|
export async function request<T = any, R = AxiosResponse<T>, D = any>(config: AxiosRequestConfig): Promise<R> {
|
||||||
|
|||||||
@ -10,6 +10,16 @@ export async function login(email: string, password: string): Promise<boolean> {
|
|||||||
return response.status === 200
|
return response.status === 200
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function register(email: string, password: string): Promise<boolean> {
|
||||||
|
const response = await request({
|
||||||
|
method: 'POST',
|
||||||
|
url: 'register',
|
||||||
|
data: {email, password}
|
||||||
|
})
|
||||||
|
return response.status === 201
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export async function getUser(): Promise<User> {
|
export async function getUser(): Promise<User> {
|
||||||
const response = await request<User>({
|
const response = await request<User>({
|
||||||
url: 'me'
|
url: 'me'
|
||||||
|
|||||||
@ -13,7 +13,8 @@ class InstanceController extends AbstractController
|
|||||||
|
|
||||||
$instance
|
$instance
|
||||||
->setLimitedFeatures($this->getParameter('limited_features') ?? false)
|
->setLimitedFeatures($this->getParameter('limited_features') ?? false)
|
||||||
->setOauthEnabled($this->getParameter('oauth_enabled'));
|
->setOauthEnabled($this->getParameter('oauth_enabled') ?? false)
|
||||||
|
->setRegisterEnabled($this->getParameter('registration_enabled') ?? false);
|
||||||
|
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ use Symfony\Component\HttpFoundation\Response;
|
|||||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||||
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
|
use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
|
||||||
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
|
||||||
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
|
||||||
use Symfony\Component\Mime\Address;
|
use Symfony\Component\Mime\Address;
|
||||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||||
@ -31,6 +32,7 @@ class RegistrationController extends AbstractController
|
|||||||
private readonly EntityManagerInterface $em,
|
private readonly EntityManagerInterface $em,
|
||||||
private readonly SerializerInterface $serializer,
|
private readonly SerializerInterface $serializer,
|
||||||
private readonly LoggerInterface $logger,
|
private readonly LoggerInterface $logger,
|
||||||
|
private readonly KernelInterface $kernel
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ class RegistrationController extends AbstractController
|
|||||||
|
|
||||||
$limiter = $this->userRegisterLimiter->create($request->getClientIp());
|
$limiter = $this->userRegisterLimiter->create($request->getClientIp());
|
||||||
|
|
||||||
if (false === $limiter->consume()->isAccepted()) {
|
if (false === $this->kernel->isDebug() && false === $limiter->consume()->isAccepted()) {
|
||||||
$this->logger->warning('IP address {ip} was rate limited by the Registration API.', [
|
$this->logger->warning('IP address {ip} was rate limited by the Registration API.', [
|
||||||
'ip' => $request->getClientIp(),
|
'ip' => $request->getClientIp(),
|
||||||
]);
|
]);
|
||||||
@ -90,7 +92,7 @@ class RegistrationController extends AbstractController
|
|||||||
->htmlTemplate('emails/success/confirmation_email.html.twig')
|
->htmlTemplate('emails/success/confirmation_email.html.twig')
|
||||||
);
|
);
|
||||||
|
|
||||||
return $this->redirectToRoute('index');
|
return new Response(null, 201);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route('/verify/email', name: 'app_verify_email')]
|
#[Route('/verify/email', name: 'app_verify_email')]
|
||||||
|
|||||||
@ -20,6 +20,8 @@ class Instance
|
|||||||
{
|
{
|
||||||
private ?bool $oauthEnabled = null;
|
private ?bool $oauthEnabled = null;
|
||||||
|
|
||||||
|
private ?bool $registerEnabled = null;
|
||||||
|
|
||||||
private ?bool $limitedFeatures = null;
|
private ?bool $limitedFeatures = null;
|
||||||
|
|
||||||
public function isSsoLogin(): ?bool
|
public function isSsoLogin(): ?bool
|
||||||
@ -45,4 +47,16 @@ class Instance
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getRegisterEnabled(): ?bool
|
||||||
|
{
|
||||||
|
return $this->registerEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRegisterEnabled(?bool $registerEnabled): static
|
||||||
|
{
|
||||||
|
$this->registerEnabled = $registerEnabled;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,46 @@ msgstr ""
|
|||||||
"Content-Type: text/plain; charset=utf-8\n"
|
"Content-Type: text/plain; charset=utf-8\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:47
|
||||||
|
#: assets/components/RegisterForm.tsx:33
|
||||||
|
msgid "Error"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:62
|
||||||
|
#: assets/components/RegisterForm.tsx:48
|
||||||
|
msgid "E-mail"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:64
|
||||||
|
#: assets/components/LoginForm.tsx:72
|
||||||
|
#: assets/components/RegisterForm.tsx:50
|
||||||
|
#: assets/components/RegisterForm.tsx:58
|
||||||
|
#: assets/components/search/DomainSearchBar.tsx:23
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:40
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:66
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:74
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:81
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:89
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:97
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:110
|
||||||
|
#: assets/components/tracking/ConnectorForm.tsx:119
|
||||||
|
#: assets/components/tracking/WatchlistForm.tsx:103
|
||||||
|
msgid "Required"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:70
|
||||||
|
#: assets/components/RegisterForm.tsx:56
|
||||||
|
msgid "Password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:80
|
||||||
|
msgid "Submit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/LoginForm.tsx:85
|
||||||
|
msgid "Log in with SSO"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/search/EventTimeline.tsx:25
|
#: assets/components/search/EventTimeline.tsx:25
|
||||||
msgid "Registration"
|
msgid "Registration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -47,21 +87,6 @@ msgstr ""
|
|||||||
msgid "ENUM validation expiration"
|
msgid "ENUM validation expiration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/search/DomainSearchBar.tsx:23
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:40
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:66
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:74
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:81
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:89
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:97
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:110
|
|
||||||
#: assets/components/tracking/ConnectorForm.tsx:119
|
|
||||||
#: assets/components/tracking/WatchlistForm.tsx:103
|
|
||||||
#: assets/pages/LoginPage.tsx:71
|
|
||||||
#: assets/pages/LoginPage.tsx:79
|
|
||||||
msgid "Required"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/components/search/DomainSearchBar.tsx:26
|
#: assets/components/search/DomainSearchBar.tsx:26
|
||||||
#: assets/components/tracking/WatchlistForm.tsx:106
|
#: assets/components/tracking/WatchlistForm.tsx:106
|
||||||
msgid "This domain name does not appear to be valid"
|
msgid "This domain name does not appear to be valid"
|
||||||
@ -326,10 +351,15 @@ msgid "Log out"
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/components/Sider.tsx:120
|
#: assets/components/Sider.tsx:120
|
||||||
#: assets/pages/LoginPage.tsx:49
|
#: assets/pages/LoginPage.tsx:30
|
||||||
msgid "Log in"
|
msgid "Log in"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/components/RegisterForm.tsx:65
|
||||||
|
#: assets/pages/LoginPage.tsx:30
|
||||||
|
msgid "Register"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/search/DomainSearchPage.tsx:20
|
#: assets/pages/search/DomainSearchPage.tsx:20
|
||||||
msgid "Found !"
|
msgid "Found !"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -434,7 +464,6 @@ msgid ""
|
|||||||
"their country of origin."
|
"their country of origin."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:69
|
|
||||||
#: assets/pages/watchdog/UserPage.tsx:18
|
#: assets/pages/watchdog/UserPage.tsx:18
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -463,22 +492,6 @@ msgstr ""
|
|||||||
msgid "Sorry, the page you visited does not exist."
|
msgid "Sorry, the page you visited does not exist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:54
|
|
||||||
msgid "Error"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:77
|
|
||||||
msgid "Password"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:86
|
|
||||||
msgid "Submit"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/pages/LoginPage.tsx:91
|
|
||||||
msgid "Log in with SSO"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: assets/utils/providers/index.tsx:11
|
#: assets/utils/providers/index.tsx:11
|
||||||
msgid ""
|
msgid ""
|
||||||
"Retrieve a set of tokens from your customer account on the Provider's "
|
"Retrieve a set of tokens from your customer account on the Provider's "
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user