Aller au contenu

Validation de schémas

Pourquoi / où / comment / valider les données ?

Il s'agit de vérifier que les données envoyées par le front-end (formulaire utilisateur, ...) sont conformes au format attendu par le back-end.

Validation client vs. validation serveur

La validation peut avoir lieu en deux endroits, avec des rôles différents

  • sur le front-end, elle permet de fournir un retour immédiat à l'utilisateur, mais ne garantit rien en termes de sécurité (on peut très bien attaquer le backend directement via curl avec des données invalides)

  • sur le back-end, elle permet de s'assurer qu'aucune opération invalide ne sera exécutée.

Validation différentes sur un même objet

Il peut y avoir plusieurs niveaux de validation sur un même objet, par exemple :

  • Création d'un utilisateur :
    • l'adresse e-mail ne doit pas déjà exister
    • le mot de passe doit avoir une longueur minimale
  • L'utilisateur modifie ses préférences :
    • Il ne peut pas modifier son identifiant
    • si l'adresse e-mail est modifiée, la nouvelle valeur doit pas déjà exister
    • le mot de passe saisi peut être vide (pas de changement)
  • L'admin modifie un utilisateur :
    • Il peut en plus modifier l'identifiant de l'utilisateur

Validation coté client : La librairie Yup

Yup peut être utilisée pour valider des données de formulaire, notamment en conjonction avec React-hook-form. Elle s'installe via npm.

Exemple :

import { object, string, number, date } from 'yup';

let userSchema = object({
  name:      string().required(),
  age:       number().required().positive().integer(),
  email:     string().email(),
  website:   string().url().nullable(),
  createdOn: date().default(() => new Date()),
}).noUnknown();  // Pas de champs supplémentaires

// parse and assert validity
const user = await userSchema.validate(await fetchUser());

Yup permet de faire des validations via des fonctions (par exemple, vérifier si un identifiant ou une adresse e-mail est déjà utilisée dans la base de données).

Attention, par défaut, les champs supplémentaires (présents dans les données, mais pas dans le schéma) sont acceptés sans validation. Pour les ignorer, spécifier .noUnknown().

Note : il est également possible de créer des schémas via des factories, c'est-à-dire des fonctions qui renvoient des schémas. Cela peut-être utile pour valider des formulaires de modification d'objets :

function makeUserSchema (user) {
  return object({ ... }) // schéma paramétré en fonction d'un utilisateur donné
}

const userSchema = makeUserSchema(user);

Validation côté serveur

La validation côté serveur, indispensable, peut être faite à l'aide d'un module Python tel que pydantic (recommandé !) ou schema.

Pydantic

Pour l'instant, voir la doc officielle.

Schema

Le module Python schema est très proche de yup :

from schema import And, Optional, Schema, Use

schema = Schema([{'name':             And(str, len),
                  'age':              And(Use(int), lambda n: 18 <= n <= 99),
                  Optional('gender'): And(str, Use(str.lower),
                                          lambda s: s in ('squid', 'kid'))}])

data = [{'name': 'Sue', 'age': '28', 'gender': 'Squid'},
        {'name': 'Sam', 'age': '42'},
        {'name': 'Sacha', 'age': '20', 'gender': 'KID'}]

validated = schema.validate(data)

Note : comme pour Yup, les schémas côté serveur peuvent être créés via des fonctions factories.