David Headrick 0e099bfd07 Enhance authentication and logging mechanisms
Updated authentication handling in controllers, added JWT support, and improved error logging. Introduced centralized API calls with customFetch for better token management. Added Grafana's Faro SDK for monitoring and tracing. Refactored project files for improved structure and maintainability.
2025-05-19 17:26:37 -05:00

107 lines
4.0 KiB
TypeScript

import { useState, FormEvent } from 'react';
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, TextField, Typography, Box, IconButton } from '@mui/material';
import { Close as CloseIcon } from '@mui/icons-material';
import utils from '@/utils/utils';
import { useCustomFetch } from "@/utils/customFetch";
type FormErrors = Record<string, string>;
type ForgotPasswordModalProps = {
show: boolean;
onClose: () => void;
};
const ForgotPasswordModal: React.FC<ForgotPasswordModalProps> = ({ show, onClose }) => {
const customFetch = useCustomFetch();
const [username, setUsername] = useState('');
const [formErrors, setFormErrors] = useState<FormErrors>({});
const [usernameNotFound, setUsernameNotFound] = useState(false);
const [recoveryStarted, setRecoveryStarted] = useState(false);
const validate = (): boolean => {
setFormErrors({});
const errors: FormErrors = {};
if (!username.trim()) {
errors.username = 'Username is required';
}
if (Object.keys(errors).length > 0) {
setFormErrors(errors);
return false;
}
return true;
};
const handleStartPasswordRecovery = async (e: FormEvent) => {
e.preventDefault();
setUsernameNotFound(false);
if (validate()) {
console.log('Processing forgot password for', username);
const apiUrl = "/api/authentication/generatepasswordrecovery";
const response = await customFetch(apiUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username}),
});
if (response.ok) {
const data = await response.json();
if (data && utils.getBoolean(data.success)) {
setRecoveryStarted(true);
return;
}
}
setUsernameNotFound(true);
}
};
return (
<Dialog open={show} onClose={() => { }}>
<DialogTitle>
Forgot your password?
<IconButton onClick={onClose} sx={{ position: 'absolute', right: 8, top: 8 }}>
<CloseIcon />
</IconButton>
</DialogTitle>
<DialogContent>
{usernameNotFound && (
<Typography color="error" sx={{ mb: 2 }}>
An email has been sent to the address you provided. Please follow the instructions to reset your password.
</Typography>
)}
{!recoveryStarted && (
<form onSubmit={handleStartPasswordRecovery}>
<Box sx={{ mb: 2 }}>
<Typography variant="body1" sx={{ mb: 2, textAlign: 'center' }}>
Enter your username below and we'll send you instructions on how to reset your password...
</Typography>
<TextField
label="Username"
variant="outlined"
fullWidth
value={username}
onChange={(e) => setUsername(e.target.value)}
error={!!formErrors.username}
helperText={formErrors.username}
required
autoFocus
size="small"
/>
</Box>
<Button type="submit" variant="contained" color="primary" fullWidth>
Submit
</Button>
</form>
)}
</DialogContent>
<DialogActions>
<Button onClick={onClose} color="secondary">
Close
</Button>
</DialogActions>
</Dialog>
);
};
export default ForgotPasswordModal;