mirror of
https://github.com/maelgangloff/domain-watchdog.git
synced 2025-12-29 16:15:04 +00:00
feat: register an account
This commit is contained in:
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 {Alert, Button, Card, Form, Input} from "antd";
|
||||
import {getConfiguration, getUser, InstanceConfig, login} from "../utils/api";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import React, {createContext, useEffect, useState} from "react";
|
||||
import {Button, Card} from "antd";
|
||||
import {t} from 'ttag'
|
||||
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 = {
|
||||
width: '50%',
|
||||
@@ -19,79 +16,27 @@ export const AuthenticatedContext = createContext<any>(null)
|
||||
|
||||
export default function LoginPage() {
|
||||
|
||||
const [error, setError] = useState<string>()
|
||||
const [wantRegister, setWantRegister] = useState<boolean>(false)
|
||||
const [configuration, setConfiguration] = useState<InstanceConfig>()
|
||||
const navigate = useNavigate()
|
||||
const {setIsAuthenticated} = useContext(AuthenticatedContext)
|
||||
|
||||
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'])
|
||||
}
|
||||
})
|
||||
const toggleWantRegister = () => {
|
||||
setWantRegister(!wantRegister)
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
getUser().then(() => {
|
||||
setIsAuthenticated(true)
|
||||
navigate('/home')
|
||||
})
|
||||
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}>
|
||||
{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`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>
|
||||
{wantRegister ? <RegisterForm/> : <LoginForm ssoLogin={configuration?.ssoLogin}/>}
|
||||
{
|
||||
configuration?.registerEnabled &&
|
||||
<Button type='link'
|
||||
block
|
||||
style={{marginTop: '1em'}}
|
||||
onClick={toggleWantRegister}>{wantRegister ? 'Login' : 'Create an account'}</Button>
|
||||
}
|
||||
</Card.Grid>
|
||||
<Card.Grid style={gridStyle} hoverable={false}>
|
||||
<TextPage resource='ads.md'/>
|
||||
|
||||
@@ -74,6 +74,7 @@ export interface Watchlist {
|
||||
export interface InstanceConfig {
|
||||
ssoLogin: boolean
|
||||
limtedFeatures: boolean
|
||||
registerEnabled: boolean
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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> {
|
||||
const response = await request<User>({
|
||||
url: 'me'
|
||||
|
||||
Reference in New Issue
Block a user