|
- import React, { useState, useEffect } from 'react';
- import axios from 'axios';
- import { QRCodeSVG } from 'qrcode.react'; // Use SVG for sharp rendering
- import {apiPath} from "../../auth/utils";
-
- import {
- Box,
- Button,
- Typography,
- TextField,
- Card,
- CardContent,
- Alert,
- CircularProgress
- } from '@mui/material';
-
- const Profile = () => {
- const [qrUrl, setQrUrl] = useState('');
- const [code, setCode] = useState('');
- const [loading, setLoading] = useState(false);
- const [message, setMessage] = useState('');
- const [error, setError] = useState('');
-
- useEffect(() => {
- // Fetch current user or check Redux store for twoFactorEnabled
- // Hide "Enable" button if already true
- }, []);
-
- const start2FASetup = async () => {
- setLoading(true);
- setMessage('');
- setError('');
- try {
- const response = await axios.post(`${apiPath}/2fa/setup`, {}, {
- headers: { Authorization: `Bearer ${localStorage.getItem('accessToken')}` } // Adjust to your auth method
- });
- setQrUrl(response.data.otpauthUrl);
- } catch (err) {
- setError('Failed to start 2FA setup. Please try again.');
- } finally {
- setLoading(false);
- }
- };
-
- const verifyCode = async () => {
- setLoading(true);
- setMessage('');
- setError('');
- try {
- await axios.post(`${apiPath}/2fa/verify-setup`, { code }, {
- headers: { Authorization: `Bearer ${localStorage.getItem('accessToken')}` }
- });
- setMessage('2FA enabled successfully! You will now be prompted for a code on login.');
- setQrUrl('');
- setCode('');
- } catch (err) {
- setError('Invalid or expired code. Try again.');
- } finally {
- setLoading(false);
- }
- };
-
- return (
- <Box sx={{ maxWidth: 800, mx: 'auto', mt: 4 }}>
- <Typography variant="h4" gutterBottom>
- Profile & Security
- </Typography>
-
- <Card sx={{ mt: 3 }}>
- <CardContent>
- <Typography variant="h6" gutterBottom>
- Two-Factor Authentication (2FA)
- </Typography>
-
- {!qrUrl ? (
- <>
- <Typography variant="body1" paragraph>
- Add an extra layer of security to your account with 2FA using Microsoft Authenticator.
- </Typography>
- <Button
- variant="contained"
- color="primary"
- onClick={start2FASetup}
- disabled={loading}
- >
- {loading ? <CircularProgress size={24} /> : 'Enable 2FA'}
- </Button>
- </>
- ) : (
- <Box sx={{ textAlign: 'center', my: 4 }}>
- <Typography variant="body1" gutterBottom>
- Scan this QR code with <strong>Microsoft Authenticator</strong>:
- </Typography>
- <QRCodeSVG value={qrUrl} size={220} level="M" />
- <Typography variant="caption" display="block" sx={{ mt: 2, mb: 3 }}>
- After scanning, enter the 6-digit code from the app:
- </Typography>
- <TextField
- label="Verification Code"
- value={code}
- onChange={(e) => setCode(e.target.value.replace(/\D/g, '').slice(0, 6))}
- inputProps={{ maxLength: 6 }}
- sx={{ width: 200 }}
- />
- <Box sx={{ mt: 2 }}>
- <Button
- variant="contained"
- onClick={verifyCode}
- disabled={loading || code.length !== 6}
- >
- {loading ? <CircularProgress size={24} /> : 'Verify & Enable'}
- </Button>
- </Box>
- </Box>
- )}
-
- {message && <Alert severity="success" sx={{ mt: 2 }}>{message}</Alert>}
- {error && <Alert severity="error" sx={{ mt: 2 }}>{error}</Alert>}
- </CardContent>
- </Card>
-
- {/* Add other profile fields here later */}
- </Box>
- );
- };
-
- export default Profile;
|