TP02-Security-Bloc4/src/pages/Profile.tsx
2025-07-30 14:47:50 +02:00

167 lines
No EOL
5.7 KiB
TypeScript

import { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { useStore } from '@/lib/store';
import Navbar from '@/components/layout/Navbar';
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { User } from '@/lib/types';
export default function ProfilePage() {
const { currentUser, logout } = useStore();
const [user, setUser] = useState<User | null>(null);
const [email, setEmail] = useState('');
const [error, setError] = useState('');
const [success, setSuccess] = useState('');
const navigate = useNavigate();
// Vulnérabilité intentionnelle: récupération de session non sécurisée
useEffect(() => {
if (currentUser) {
setUser(currentUser);
setEmail(currentUser.email);
} else {
// Récupération depuis localStorage sans vérifications
const storedUserId = localStorage.getItem('userId');
if (storedUserId) {
// Cette vulnérabilité suppose qu'on fait confiance au userId stocké localement
// sans vérifier l'authenticité du token
const users = useStore.getState().users;
const foundUser = users.find(u => u.id === parseInt(storedUserId));
if (foundUser) {
setUser(foundUser);
setEmail(foundUser.email);
} else {
navigate('/login');
}
} else {
navigate('/login');
}
}
}, [currentUser, navigate]);
// Vulnérabilité intentionnelle: pas de protection CSRF
const handleUpdateProfile = (e: React.FormEvent) => {
e.preventDefault();
if (!email) {
setError('L\'email est obligatoire');
return;
}
if (user) {
// Vulnérabilité intentionnelle: pas de validation complexe
// Pas de changement réel car ce n'est qu'une simulation
setSuccess('Profil mis à jour avec succès !');
setError('');
} else {
setError('Utilisateur non authentifié');
}
};
// Vulnérabilité intentionnelle: pas de confirmation pour action sensible
const handleDeleteAccount = () => {
// Simule une suppression de compte sans confirmation
logout();
navigate('/');
};
if (!user) {
return <div>Chargement...</div>;
}
return (
<div className="min-h-screen flex flex-col bg-slate-50">
<Navbar />
<div className="container mx-auto py-8 px-4 flex-grow">
<div className="max-w-md mx-auto">
<Card>
<CardHeader>
<CardTitle>Mon Profil</CardTitle>
<CardDescription>
Gérez vos informations personnelles
</CardDescription>
</CardHeader>
<CardContent>
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 p-3 rounded mb-4">
{error}
</div>
)}
{success && (
<div className="bg-green-50 border border-green-200 text-green-700 p-3 rounded mb-4">
{success}
</div>
)}
<form onSubmit={handleUpdateProfile}>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="username">Nom d'utilisateur</Label>
<Input
id="username"
value={user.username}
disabled
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>
<div className="space-y-2">
<Label htmlFor="role">Rôle</Label>
<Input
id="role"
value={user.role}
disabled
/>
</div>
{/* Vulnérabilité intentionnelle: exposition de données sensibles */}
<div className="space-y-2 bg-yellow-50 border border-yellow-200 p-4 rounded">
<Label htmlFor="password">Mot de passe (en clair pour démonstration)</Label>
<Input
id="password"
value={user.password}
disabled
/>
<p className="text-xs text-yellow-600">
Note: Cette exposition est une vulnérabilité intentionnelle à des fins éducatives.
</p>
</div>
</div>
<Button type="submit" className="w-full mt-6">
Mettre à jour le profil
</Button>
</form>
</CardContent>
<CardFooter className="flex flex-col">
<Button
variant="destructive"
className="w-full mt-2"
onClick={handleDeleteAccount}
>
Supprimer mon compte
</Button>
<p className="text-xs text-gray-500 mt-2">
Note: La suppression est immédiate sans confirmation (vulnérabilité intentionnelle).
</p>
</CardFooter>
</Card>
</div>
</div>
</div>
);
}