Files
webapp-forumexam/client/src/components/Auth.jsx
2025-06-28 18:31:48 +02:00

140 lines
4.0 KiB
JavaScript

import { useState } from 'react';
import { Form, Button, Alert, Col, Row } from 'react-bootstrap';
import { useNavigate } from 'react-router';
import API from '../API.js'
function TotpForm(props) {
const [totpCode, setTotpCode] = useState('');
const [errorMessage, setErrorMessage] = useState('');
const navigate = useNavigate();
const doTotpVerify = () => {
API.totpVerify(totpCode)
.then(() => {
setErrorMessage('');
props.totpSuccessful();
navigate('/');
})
.catch(() => {
setErrorMessage('Something went wrong, please try again');
})
}
const handleSubmit = (event) => {
event.preventDefault();
setErrorMessage('');
let valid = true;
if(totpCode === '' || totpCode.length !== 6)
valid = false;
if (valid) {
doTotpVerify(totpCode);
} else {
setErrorMessage('Invalid content in form: either empty or not 6-char long');
}
};
return (
<Row>
<Col xs={4}></Col>
<Col xs={4}>
<h2>Second Factor Authentication</h2>
<h5>Please enter the code that you read on your device</h5>
<Form onSubmit={handleSubmit}>
{errorMessage ? <Alert variant='danger' dismissible onClick={() => setErrorMessage('')}>{errorMessage}</Alert> : ''}
<Form.Group controlId='totpCode'>
<Form.Label>Code</Form.Label>
<Form.Control type='text' required={true} value={totpCode} onChange={ev => setTotpCode(ev.target.value)} />
</Form.Group>
<Button className='my-2' type='submit'>Validate</Button>
<Button className='my-2 mx-2' variant='danger' onClick={() => navigate('/')}>Cancel</Button>
</Form>
</Col>
<Col xs={4}></Col>
</Row>
)
}
function LoginForm(props) {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [istotp, setIstotp] = useState(false);
const [errorMessage, setErrorMessage] = useState('');
const navigate = useNavigate();
const handleSubmit = (event) => {
event.preventDefault();
const credentials = { username, password };
if (!username) {
setErrorMessage('Username cannot be empty');
} else if (!password) {
setErrorMessage('Password cannot be empty');
} else {
props.login(credentials)
.catch((err) => {
setErrorMessage(err.error);
});
}
};
return (
<Row>
<Col xs={4}></Col>
<Col xs={4}>
<h1 className="pb-3">Login</h1>
<Form onSubmit={handleSubmit}>
{errorMessage? <Alert dismissible onClose={() => setErrorMessage('')} variant="danger">{errorMessage}</Alert> : null}
<Form.Group className="mb-3">
<Form.Label>Username</Form.Label>
<Form.Control
type="username"
value={username} placeholder="Enter your username"
onChange={(ev) => setUsername(ev.target.value)}
/>
</Form.Group>
<Form.Group className="mb-3">
<Form.Label>Password</Form.Label>
<Form.Control
type="password"
value={password} placeholder="Enter your password"
onChange={(ev) => setPassword(ev.target.value)}
/>
</Form.Group>
<Form.Check type="checkbox"
label="Use OTP"
onChange={(ev) => setIstotp(ev.target.value)}
/>
<Button className="my-2" type="submit" onClick={()=> istotp ? props.checkAuth() : navigate('/')} >Login</Button>
<Button className='my-2 mx-2' variant='danger' onClick={() => navigate('/')}>Cancel</Button>
</Form>
</Col>
<Col xs={4}></Col>
</Row>
)
};
function LogoutButton(props) {
return (
<Button variant="outline-light" onClick={props.logout}>Logout</Button>
)
}
function LoginButton(props) {
const navigate = useNavigate();
return (
<Button variant="outline-light" onClick={()=> navigate('/login')}>{props.text}</Button>
)
}
export { LoginForm, LogoutButton, LoginButton, TotpForm };