167 lines
No EOL
5.7 KiB
TypeScript
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>
|
|
);
|
|
} |