ScaleRocket/Web

Validation des entrées

Patterns de validation avec les schémas Zod, validation des paramètres des Edge Functions et vérifications d'upload de fichiers.

Vue d'ensemble

La validation des entrées est essentielle pour la sécurité et l'intégrité des données. ScaleRocket utilise Zod pour la validation basée sur des schémas côté client et serveur, avec des vérifications supplémentaires pour les Edge Functions et les uploads de fichiers.

Validation par schéma Zod

Zod est la bibliothèque de validation recommandée. Définissez des schémas et validez les données avant le traitement :

Schéma de base

import { z } from "zod";

const userSchema = z.object({
  email: z.string().email("Invalid email address"),
  password: z.string().min(8, "Password must be at least 8 characters"),
  name: z.string().min(1, "Name is required").max(100),
});

type UserInput = z.infer<typeof userSchema>;

Valider les entrées

const result = userSchema.safeParse(formData);

if (!result.success) {
  // result.error.flatten() gives a structured error object
  const errors = result.error.flatten().fieldErrors;
  // { email: ["Invalid email address"], password: ["..."] }
  return;
}

// result.data is fully typed and safe to use
const { email, password, name } = result.data;

Patterns de schéma courants

// Optional field with default
const settingsSchema = z.object({
  notifications: z.boolean().default(true),
  language: z.enum(["en", "fr", "de"]).default("en"),
});

// String transformations
const slugSchema = z.string().trim().toLowerCase().regex(/^[a-z0-9-]+$/);

// Number constraints
const paginationSchema = z.object({
  page: z.coerce.number().int().positive().default(1),
  limit: z.coerce.number().int().min(1).max(100).default(20),
});

// Union types
const idSchema = z.union([z.string().uuid(), z.string().cuid()]);

Validation des formulaires côté client

Validez avant la soumission pour éviter les appels API inutiles :

const handleSubmit = (e: FormEvent) => {
  e.preventDefault();
  const result = userSchema.safeParse({ email, password, name });

  if (!result.success) {
    const errors = result.error.flatten().fieldErrors;
    setErrors(errors);
    return;
  }

  // Submit validated data
  submitForm(result.data);
};

Validation des paramètres des Edge Functions

Validez toujours les corps de requête entrants dans les Edge Functions :

import { z } from "zod";

const requestSchema = z.object({
  userId: z.string().uuid(),
  action: z.enum(["activate", "deactivate"]),
  reason: z.string().max(500).optional(),
});

Deno.serve(async (req) => {
  let body;
  try {
    body = await req.json();
  } catch {
    return new Response(JSON.stringify({ error: "Invalid JSON" }), { status: 400 });
  }

  const result = requestSchema.safeParse(body);
  if (!result.success) {
    return new Response(
      JSON.stringify({ error: "Validation failed", details: result.error.flatten().fieldErrors }),
      { status: 400 }
    );
  }

  // Use result.data safely
  const { userId, action } = result.data;
});

Validation des uploads de fichiers

Pour les uploads média admin et les pièces jointes utilisateur, validez avant le traitement :

const MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
const ALLOWED_TYPES = ["image/jpeg", "image/png", "image/webp", "application/pdf"];

function validateFile(file: File): string | null {
  if (file.size > MAX_FILE_SIZE) {
    return `File too large. Maximum size is ${MAX_FILE_SIZE / 1024 / 1024}MB.`;
  }
  if (!ALLOWED_TYPES.includes(file.type)) {
    return `Invalid file type. Allowed: ${ALLOWED_TYPES.join(", ")}`;
  }
  return null; // valid
}

Avec Zod

const fileSchema = z.object({
  name: z.string(),
  size: z.number().max(5 * 1024 * 1024, "File exceeds 5MB limit"),
  type: z.enum(["image/jpeg", "image/png", "image/webp", "application/pdf"], {
    errorMap: () => ({ message: "Unsupported file type" }),
  }),
});

Checklist de validation

  • Valider toutes les entrées de formulaire avant la soumission (côté client)
  • Valider tous les corps de requête des Edge Functions (côté serveur)
  • Utiliser safeParse au lieu de parse pour éviter de lancer des exceptions
  • Définir des longueurs maximales sur les champs string pour empêcher les abus de payload
  • Valider la taille et le type MIME des fichiers avant l'upload
  • Ne jamais faire confiance à la validation côté client seule ; toujours re-valider côté serveur

Conseils

  • Partagez les schémas Zod entre le client et le serveur en les plaçant dans un package partagé.
  • Utilisez z.coerce pour les paramètres de requête et les données de formulaire qui arrivent sous forme de chaînes de caractères.
  • Combinez Zod avec React Hook Form en utilisant @hookform/resolvers/zod pour une validation de formulaire intégrée.
  • Assainissez le contenu HTML (ex. articles de blog) avec une bibliothèque comme dompurify après la validation Zod.

Fini ? Marquez cette page comme terminée.

On this page