From b8152025299a977ff2d28244f49634e31c5e05e0 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sat, 28 Feb 2026 10:59:00 +0100 Subject: [PATCH] refactor: convert password change to Server Action - Add src/app/actions/password.ts with changePassword - Update ChangePasswordForm to use Server Action - Remove api/user/password route (entire file) --- docs/server-actions-plan.md | 1 + src/app/actions/password.ts | 33 ++++++++++++ src/app/api/user/password/route.ts | 52 ------------------- src/components/account/ChangePasswordForm.tsx | 12 ++--- 4 files changed, 38 insertions(+), 60 deletions(-) create mode 100644 src/app/actions/password.ts delete mode 100644 src/app/api/user/password/route.ts diff --git a/docs/server-actions-plan.md b/docs/server-actions-plan.md index 32e9884..2082d69 100644 --- a/docs/server-actions-plan.md +++ b/docs/server-actions-plan.md @@ -13,6 +13,7 @@ | `PUT /api/preferences` | `updatePreferences()` | ✅ Done | | `POST /api/komga/libraries/[libraryId]/scan` | `scanLibrary()` | ✅ Done | | `POST /api/komga/config` | `saveKomgaConfig()` | ✅ Done | +| `PUT /api/user/password` | `changePassword()` | ✅ Done | --- diff --git a/src/app/actions/password.ts b/src/app/actions/password.ts new file mode 100644 index 0000000..c957c1d --- /dev/null +++ b/src/app/actions/password.ts @@ -0,0 +1,33 @@ +"use server"; + +import { UserService } from "@/lib/services/user.service"; +import { AuthServerService } from "@/lib/services/auth-server.service"; +import { ERROR_CODES } from "@/constants/errorCodes"; +import { AppError } from "@/utils/errors"; + +/** + * Change le mot de passe de l'utilisateur + */ +export async function changePassword( + currentPassword: string, + newPassword: string +): Promise<{ success: boolean; message: string }> { + try { + // Vérifier que le nouveau mot de passe est fort + if (!AuthServerService.isPasswordStrong(newPassword)) { + return { + success: false, + message: "Le nouveau mot de passe doit contenir au moins 8 caractères, une majuscule et un chiffre", + }; + } + + await UserService.changePassword(currentPassword, newPassword); + + return { success: true, message: "Mot de passe modifié avec succès" }; + } catch (error) { + if (error instanceof AppError) { + return { success: false, message: error.message }; + } + return { success: false, message: "Erreur lors du changement de mot de passe" }; + } +} diff --git a/src/app/api/user/password/route.ts b/src/app/api/user/password/route.ts deleted file mode 100644 index 74e3214..0000000 --- a/src/app/api/user/password/route.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { NextRequest, NextResponse } from "next/server"; -import { UserService } from "@/lib/services/user.service"; -import { AppError } from "@/utils/errors"; -import { AuthServerService } from "@/lib/services/auth-server.service"; -import logger from "@/lib/logger"; - -export async function PUT(request: NextRequest) { - try { - const body = await request.json(); - const { currentPassword, newPassword } = body; - - if (!currentPassword || !newPassword) { - return NextResponse.json({ error: "Mots de passe manquants" }, { status: 400 }); - } - - // Vérifier que le nouveau mot de passe est fort - if (!AuthServerService.isPasswordStrong(newPassword)) { - return NextResponse.json( - { - error: - "Le nouveau mot de passe doit contenir au moins 8 caractères, une majuscule et un chiffre", - }, - { status: 400 } - ); - } - - await UserService.changePassword(currentPassword, newPassword); - - return NextResponse.json({ success: true }); - } catch (error) { - logger.error({ err: error }, "Erreur lors du changement de mot de passe:"); - - if (error instanceof AppError) { - return NextResponse.json( - { error: error.message, code: error.code }, - { - status: - error.code === "AUTH_INVALID_PASSWORD" - ? 400 - : error.code === "AUTH_UNAUTHENTICATED" - ? 401 - : 500, - } - ); - } - - return NextResponse.json( - { error: "Erreur lors du changement de mot de passe" }, - { status: 500 } - ); - } -} diff --git a/src/components/account/ChangePasswordForm.tsx b/src/components/account/ChangePasswordForm.tsx index dcffc50..9fe87ba 100644 --- a/src/components/account/ChangePasswordForm.tsx +++ b/src/components/account/ChangePasswordForm.tsx @@ -7,6 +7,7 @@ import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { useToast } from "@/components/ui/use-toast"; import { Lock } from "lucide-react"; +import { changePassword } from "@/app/actions/password"; export function ChangePasswordForm() { const [currentPassword, setCurrentPassword] = useState(""); @@ -39,15 +40,10 @@ export function ChangePasswordForm() { setIsLoading(true); try { - const response = await fetch("/api/user/password", { - method: "PUT", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify({ currentPassword, newPassword }), - }); + const result = await changePassword(currentPassword, newPassword); - if (!response.ok) { - const data = await response.json(); - throw new Error(data.error || "Erreur lors du changement de mot de passe"); + if (!result.success) { + throw new Error(result.message); } toast({