diff --git a/client/src/pages/Login.tsx b/client/src/pages/Login.tsx index 6edecb6..7221f36 100644 --- a/client/src/pages/Login.tsx +++ b/client/src/pages/Login.tsx @@ -1,19 +1,31 @@ import { useState } from "react"; import { useForm } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; +import { useQuery } from "@tanstack/react-query"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"; +import { Alert, AlertDescription } from "@/components/ui/alert"; import { useToast } from "@/hooks/use-toast"; import { useAuth } from "@/hooks/useAuth"; import { loginSchema, type LoginData } from "@shared/schema"; -import { LogIn, Sparkles } from "lucide-react"; +import { LogIn, Sparkles, Info } from "lucide-react"; +import { apiRequest } from "@/lib/queryClient"; export default function Login() { const { login, isLoggingIn } = useAuth(); const { toast } = useToast(); + // Check if default credentials should be shown + const { data: credentialsStatus } = useQuery({ + queryKey: ['/api/auth/default-credentials-status'], + queryFn: async () => { + const response = await apiRequest('/api/auth/default-credentials-status'); + return response.json(); + }, + }); + const form = useForm({ resolver: zodResolver(loginSchema), defaultValues: { @@ -86,13 +98,23 @@ export default function Login() { -
-

Compte par défaut :

-
-

Utilisateur : admin

-

Mot de passe : admin123

-
-
+ {credentialsStatus?.showDefaultCredentials && ( + + + +
+

Compte administrateur par défaut :

+
+

Utilisateur : admin

+

Mot de passe : admin123

+
+

+ ⚠️ Changez ce mot de passe après votre première connexion pour sécuriser l'application. +

+
+
+
+ )} diff --git a/replit.md b/replit.md index f67b3be..a34c963 100644 --- a/replit.md +++ b/replit.md @@ -174,4 +174,10 @@ Preferred communication style: Simple, everyday language. - ✅ Backup files stored in server/backups/ directory with timestamped filenames - ✅ Enhanced administration interface showing backup statistics and manual backup creation - ✅ Real-time backup status monitoring with automatic stats refresh every 30 seconds -- ✅ Initial backup creation on server startup if no backups exist \ No newline at end of file +- ✅ Initial backup creation on server startup if no backups exist + +### Security Improvements (January 9, 2025) +- ✅ Enhanced login page to hide default admin credentials (admin/admin123) once password is changed +- ✅ Added dynamic credential visibility based on whether default password is still in use +- ✅ Security warning displayed when default credentials are shown +- ✅ API endpoint to check default credential status with password hash comparison \ No newline at end of file diff --git a/server/routes.ts b/server/routes.ts index 7f53a3f..f8e4a74 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -105,6 +105,17 @@ export async function registerRoutes(app: Express): Promise { }); }); + // Check if default admin credentials are still in use + app.get('/api/auth/default-credentials-status', async (req, res) => { + try { + const isUsingDefault = await storage.isUsingDefaultPassword(); + res.json({ showDefaultCredentials: isUsingDefault }); + } catch (error) { + console.error('Default credentials check error:', error); + res.status(500).json({ error: "Failed to check default credentials status" }); + } + }); + app.get('/api/auth/me', requireAuth, async (req, res) => { try { const user = await storage.getUser(req.session.userId!); diff --git a/server/storage.ts b/server/storage.ts index caf4b29..595711f 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -39,6 +39,7 @@ export interface IStorage { authenticateUser(username: string, password: string): Promise; hashPassword(password: string): Promise; initializeDefaults(): Promise<{ defaultAdminCredentials?: { username: string; password: string } }>; + isUsingDefaultPassword(): Promise; } export class DatabaseStorage implements IStorage { @@ -168,6 +169,17 @@ export class DatabaseStorage implements IStorage { return await bcrypt.hash(password, 12); } + // Check if admin still uses default password + async isUsingDefaultPassword(): Promise { + const adminUser = await this.getUserByUsername('admin'); + if (!adminUser) { + return false; + } + + // Check if the stored password hash matches the default password "admin123" + return await bcrypt.compare('admin123', adminUser.password); + } + // Initialize default admin user and store if none exist async initializeDefaults(): Promise<{ defaultAdminCredentials?: { username: string; password: string } }> { const existingUsers = await this.getAllUsers();