refactor: convert admin user management to Server Actions
- Add src/app/actions/admin.ts with updateUserRoles, deleteUser, resetUserPassword - Update EditUserDialog, DeleteUserDialog, ResetPasswordDialog to use Server Actions - Remove admin users API routes (PATCH/DELETE/PUT)
This commit is contained in:
72
src/app/actions/admin.ts
Normal file
72
src/app/actions/admin.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
"use server";
|
||||
|
||||
import { AdminService } from "@/lib/services/admin.service";
|
||||
import { ERROR_CODES } from "@/constants/errorCodes";
|
||||
import { AppError } from "@/utils/errors";
|
||||
import { AuthServerService } from "@/lib/services/auth-server.service";
|
||||
|
||||
/**
|
||||
* Met à jour les rôles d'un utilisateur
|
||||
*/
|
||||
export async function updateUserRoles(
|
||||
userId: string,
|
||||
roles: string[]
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
try {
|
||||
if (roles.length === 0) {
|
||||
return { success: false, message: "L'utilisateur doit avoir au moins un rôle" };
|
||||
}
|
||||
|
||||
await AdminService.updateUserRoles(userId, roles);
|
||||
|
||||
return { success: true, message: "Rôles mis à jour" };
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
return { success: false, message: error.message };
|
||||
}
|
||||
return { success: false, message: "Erreur lors de la mise à jour des rôles" };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Supprime un utilisateur
|
||||
*/
|
||||
export async function deleteUser(
|
||||
userId: string
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
try {
|
||||
await AdminService.deleteUser(userId);
|
||||
return { success: true, message: "Utilisateur supprimé" };
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
return { success: false, message: error.message };
|
||||
}
|
||||
return { success: false, message: "Erreur lors de la suppression" };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Réinitialise le mot de passe d'un utilisateur
|
||||
*/
|
||||
export async function resetUserPassword(
|
||||
userId: string,
|
||||
newPassword: string
|
||||
): Promise<{ success: boolean; message: string }> {
|
||||
try {
|
||||
if (!AuthServerService.isPasswordStrong(newPassword)) {
|
||||
return {
|
||||
success: false,
|
||||
message: "Le mot de passe doit contenir au moins 8 caractères, une majuscule et un chiffre",
|
||||
};
|
||||
}
|
||||
|
||||
await AdminService.resetUserPassword(userId, newPassword);
|
||||
|
||||
return { success: true, message: "Mot de passe réinitialisé" };
|
||||
} catch (error) {
|
||||
if (error instanceof AppError) {
|
||||
return { success: false, message: error.message };
|
||||
}
|
||||
return { success: false, message: "Erreur lors de la réinitialisation du mot de passe" };
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { AdminService } from "@/lib/services/admin.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,
|
||||
{ params }: { params: Promise<{ userId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { userId } = await params;
|
||||
const body = await request.json();
|
||||
const { newPassword } = body;
|
||||
|
||||
if (!newPassword) {
|
||||
return NextResponse.json({ error: "Nouveau mot de passe manquant" }, { status: 400 });
|
||||
}
|
||||
|
||||
// Vérifier que le mot de passe est fort
|
||||
if (!AuthServerService.isPasswordStrong(newPassword)) {
|
||||
return NextResponse.json(
|
||||
{
|
||||
error: "Le mot de passe doit contenir au moins 8 caractères, une majuscule et un chiffre",
|
||||
},
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
await AdminService.resetUserPassword(userId, newPassword);
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
logger.error({ err: error }, "Erreur lors de la réinitialisation du mot de passe:");
|
||||
|
||||
if (error instanceof AppError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{
|
||||
status:
|
||||
error.code === "AUTH_FORBIDDEN"
|
||||
? 403
|
||||
: error.code === "AUTH_UNAUTHENTICATED"
|
||||
? 401
|
||||
: error.code === "AUTH_USER_NOT_FOUND"
|
||||
? 404
|
||||
: error.code === "ADMIN_CANNOT_RESET_OWN_PASSWORD"
|
||||
? 400
|
||||
: 500,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la réinitialisation du mot de passe" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { AdminService } from "@/lib/services/admin.service";
|
||||
import { AppError } from "@/utils/errors";
|
||||
import logger from "@/lib/logger";
|
||||
|
||||
export async function PATCH(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ userId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { userId } = await params;
|
||||
const body = await request.json();
|
||||
const { roles } = body;
|
||||
|
||||
if (!roles || !Array.isArray(roles)) {
|
||||
return NextResponse.json({ error: "Rôles invalides" }, { status: 400 });
|
||||
}
|
||||
|
||||
await AdminService.updateUserRoles(userId, roles);
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
logger.error({ err: error }, "Erreur lors de la mise à jour de l'utilisateur:");
|
||||
|
||||
if (error instanceof AppError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{
|
||||
status:
|
||||
error.code === "AUTH_FORBIDDEN"
|
||||
? 403
|
||||
: error.code === "AUTH_UNAUTHENTICATED"
|
||||
? 401
|
||||
: error.code === "AUTH_USER_NOT_FOUND"
|
||||
? 404
|
||||
: 500,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la mise à jour de l'utilisateur" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(
|
||||
request: NextRequest,
|
||||
{ params }: { params: Promise<{ userId: string }> }
|
||||
) {
|
||||
try {
|
||||
const { userId } = await params;
|
||||
await AdminService.deleteUser(userId);
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
logger.error({ err: error }, "Erreur lors de la suppression de l'utilisateur:");
|
||||
|
||||
if (error instanceof AppError) {
|
||||
return NextResponse.json(
|
||||
{ error: error.message, code: error.code },
|
||||
{
|
||||
status:
|
||||
error.code === "AUTH_FORBIDDEN"
|
||||
? 403
|
||||
: error.code === "AUTH_UNAUTHENTICATED"
|
||||
? 401
|
||||
: error.code === "AUTH_USER_NOT_FOUND"
|
||||
? 404
|
||||
: error.code === "ADMIN_CANNOT_DELETE_SELF"
|
||||
? 400
|
||||
: 500,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json(
|
||||
{ error: "Erreur lors de la suppression de l'utilisateur" },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import type { AdminUserData } from "@/lib/services/admin.service";
|
||||
import { deleteUser } from "@/app/actions/admin";
|
||||
|
||||
interface DeleteUserDialogProps {
|
||||
user: AdminUserData;
|
||||
@@ -29,13 +30,10 @@ export function DeleteUserDialog({ user, open, onOpenChange, onSuccess }: Delete
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${user.id}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
const result = await deleteUser(user.id);
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json();
|
||||
throw new Error(data.error || "Erreur lors de la suppression");
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
toast({
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Checkbox } from "@/components/ui/checkbox";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import type { AdminUserData } from "@/lib/services/admin.service";
|
||||
import { updateUserRoles } from "@/app/actions/admin";
|
||||
|
||||
interface EditUserDialogProps {
|
||||
user: AdminUserData;
|
||||
@@ -51,15 +52,10 @@ export function EditUserDialog({ user, open, onOpenChange, onSuccess }: EditUser
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${user.id}`, {
|
||||
method: "PATCH",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ roles: selectedRoles }),
|
||||
});
|
||||
const result = await updateUserRoles(user.id, selectedRoles);
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json();
|
||||
throw new Error(data.error || "Erreur lors de la mise à jour");
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
toast({
|
||||
|
||||
@@ -15,6 +15,7 @@ import { Label } from "@/components/ui/label";
|
||||
import { useToast } from "@/components/ui/use-toast";
|
||||
import { Lock } from "lucide-react";
|
||||
import type { AdminUserData } from "@/lib/services/admin.service";
|
||||
import { resetUserPassword } from "@/app/actions/admin";
|
||||
|
||||
interface ResetPasswordDialogProps {
|
||||
user: AdminUserData;
|
||||
@@ -65,15 +66,10 @@ export function ResetPasswordDialog({
|
||||
setIsLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/admin/users/${user.id}/password`, {
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ newPassword }),
|
||||
});
|
||||
const result = await resetUserPassword(user.id, newPassword);
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json();
|
||||
throw new Error(data.error || "Erreur lors de la réinitialisation");
|
||||
if (!result.success) {
|
||||
throw new Error(result.message);
|
||||
}
|
||||
|
||||
toast({
|
||||
|
||||
Reference in New Issue
Block a user