Référence d'API — @nodefony/user
stable
Documentation › Référence d’API › @nodefony/user
Générée depuis les déclarations de types publiées de
@nodefony/user10.0.0-beta.5 : exactement ce que reçoit une application qui l’installe. Cette page n’existe dans aucun dépôt — pour la corriger, on corrige le TSDoc du code.
@nodefony/user#
import { … } from "@nodefony/user" — 73 symboles.
Classes (12)#
AnonymousUser#
class AnonymousUser implements IUser
Utilisateur non authentifié — implémente IUser sans credential.
readonly id = "anonymous"— Identifiant interne — UUID (jamaisstring | number).readonly identifier = "anon."— Identifiant fonctionnel d’authentification (email, login…).readonly roles: string[]— Rôles plats accordés (sans hiérarchie résolue).hasRole(role: string): boolean— Indique si l’utilisateur possède le rôle exact donné (sans hiérarchie).isActive(): boolean— Un anonyme est utilisable (non désactivé).isLocked(): boolean— Un anonyme n’est jamais verrouillé.
Argon2idEncoder#
class Argon2idEncoder implements IPasswordEncoder
Encodeur de mot de passe Argon2id (RFC 9106) — recommandation NIST/OWASP 2026.
readonly memoryKiB: number— Mémoire par hash (KiB) utilisée pour produire les nouveaux hashs.readonly timeCost: number— Passes sur la mémoire utilisées pour produire les nouveaux hashs.readonly parallelism: number— Lanes parallèles utilisées pour produire les nouveaux hashs.constructor(options?: Argon2idOptions)supports(hash: string): boolean— Reconnaît un hash argon2 (tous variants$argon2d|i|id$) — parsing pur, sync.hash(plain: string): Promise<string>— Hache un mot de passe en clair (sel généré, paramètres inclus dans la sortie PHC).verify(plain: string, hash: string): Promise<boolean>— Vérifie un mot de passe en clair contre un hash stocké (temps constant interne).needsRehash(hash: string): boolean— Indique si un hash doit être recalculé : format non argon2, variant nonid, version antérieure à 0x13, ou coûts stockés INFÉRIEURS aux coûts courants (politique affaiblie).
BaseUser#
class BaseUser implements IPasswordAuthenticatedUser
Implémentation POJO de référence d’un utilisateur — base partagée par tous les ORM.
readonly id: string— Identifiant interne — UUID (jamaisstring | number).readonly identifier: string— Identifiant fonctionnel d’authentification (email, login…).roles: string[]— Rôles plats accordés (sans hiérarchie résolue).password: string | null— Hash du mot de passe stocké, ounullpour un compte sans mot de passe local.currentRole: string | null— Profil de rôle actif en session (P5.11) — distinct des rôles plats.socialProviders: ISocialProvider[]metadata: Record<string, unknown>credentialsVersion: number | null— Version des identifiants — cfIUser.credentialsVersion.protected enabled: booleanprotected locked: booleanconstructor(options: IBaseUserOptions)hasRole(role: string): boolean— Indique si l’utilisateur possède le rôle exact donné (sans hiérarchie).isActive(): boolean— Indique si le compte est actif (activé et non expiré).isLocked(): boolean— Indique si le compte est verrouillé (ex.toJSON(): Omit<IBaseUserOptions, "password" | "credentialsVersion">— Forme sérialisée de l’utilisateur, SANS le hash du mot de passe ni la version des identifiants (état interne de révocation, utile à personne hors du pare-feu).addRole(role: string): this— Ajoute un rôle s’il n’est pas déjà présent (idempotent).removeRole(role: string): this— Retire un rôle s’il est présent (idempotent).addSocialProvider(link: ISocialProvider): this— Lie un compte externe (OAuth/OIDC) — pattern Shadow User.enable(): this— Active le compte.disable(): this— Désactive le compte.lock(): this— Verrouille le compte.unlock(): this— Déverrouille le compte.setCurrentRole(role: string | null): this— Définit le profil de rôle actif (session).setPassword(hash: string | null): this— Remplace le hash de mot de passe stocké.
BcryptEncoder#
class BcryptEncoder implements IPasswordEncoder
Encodeur de mot de passe bcrypt — implémentation de référence d’IPasswordEncoder.
readonly rounds: number— Coût bcrypt utilisé pour produire les nouveaux hashs.constructor(rounds?: number)supports(hash: string): boolean— Reconnaît un hash bcrypt ($2a$/$2b$/$2y$+ coût) — parsing pur, sync.hash(plain: string): Promise<string>— Hache un mot de passe en clair (sel généré et inclus dans la sortie).verify(plain: string, hash: string): Promise<boolean>— Vérifie un mot de passe en clair contre un hash stocké (temps constant interne).needsRehash(hash: string): boolean— Indique si un hash doit être recalculé (coût stocké inférieur au coût courant, ou format non bcrypt).
IdentifierImmutableError#
class IdentifierImmutableError extends nodefonyError
Une mise à jour tente de RENOMMER un compte — l’identifiant est immuable.
constructor(current: string)
IdentifierTakenError#
class IdentifierTakenError extends nodefonyError
Un compte local porte déjà cet identifiant — l’identifiant est UNIQUE dans l’annuaire, quel que soit le dépôt (index unique en SQL et en document, refus explicite en mémoire).
constructor(detail: string)
InMemoryUserRepository#
class InMemoryUserRepository implements IUserRepository
Annuaire d’utilisateurs en mémoire — implémentation de référence du contrat IUserRepository sur une Map (aucun ORM).
readonly sortableFields: readonly [ "identifier", "enabled", "id" ]— Capacité RÉELLE de cet annuaire :BaseUserne porte nicreatedAtniupdatedAt, donc ils ne sont pas annoncés.constructor(seed?: IBaseUserOptions[])find(criteria?: Criteria<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser[]>— Retourne toutes les entités correspondant au critère (toutes si omis).findOne(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>— Retourne la première entité correspondant au critère, ounull.create(data: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser>— Persiste une nouvelle entité et retourne sa version persistée (id généré, valeurs par défaut).updateOne(criteria: Criteria<IPasswordAuthenticatedUser>, data: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>— Met à jour au plus une entité correspondant au critère, de façon atomique, et retourne sa version persistée (ounullsi aucune ne correspond).upsert(criteria: Criteria<IPasswordAuthenticatedUser>, update: Partial<IPasswordAuthenticatedUser>, insertOnly?: Partial<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser>— Insère ou met à jour atomiquement l’entité identifiée parcriteria(clé unique), en une seule requête (INSERT … ON CONFLICT DO UPDATE … RETURNINGSQL /findOneAndUpdate({ upsert })Mongo …createMany(data: Partial<IPasswordAuthenticatedUser>[]): Promise<IPasswordAuthenticatedUser[]>— Insère plusieurs entités en une seule requête (INSERT … VALUES (…),(…)SQL /insertManyMongo) et retourne leurs versions persistées (ids générés, défauts appliqués), dans l’ordre.exists(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<boolean>— Indique si au moins une entité correspond au critère, sans rapatrier la ligne (SELECT 1 … LIMIT 1SQL /existsMongo).deleteOne(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<boolean>— Supprime au plus une entité de façon atomique (symétrique d’IRepository.updateOne;DELETE … LIMIT 1SQL /deleteOneMongo).findOneAndDelete(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>— Supprime au plus une entité et retourne sa valeur supprimée (ounull), de façon atomique (DELETE … RETURNINGSQL /findOneAndDeleteMongo) — claim-and-remove (file de jobs, outbox, pop a …increment(criteria: Criteria<IPasswordAuthenticatedUser>, changes: Partial<Record<keyof IPasswordAuthenticatedUser, number>>): Promise<IPasswordAuthenticatedUser | null>— Incrémente atomiquement des champs numériques d’au plus une entité (SET f = f + ?SQL /$incMongo), sans read-modify-write (donc sans race) — pour les compteurs (stats, usage/tokens, rate …updateMany(criteria: Criteria<IPasswordAuthenticatedUser>, data: Partial<IPasswordAuthenticatedUser>): Promise<number>— Met à jour toutes les entités correspondant au critère et retourne le nombre de lignes modifiées (parité de signature avecIRepository.delete).delete(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<number>— Supprime les entités correspondant au critère.count(criteria?: Criteria<IPasswordAuthenticatedUser>): Promise<number>— Compte les entités correspondant au critère (toutes si omis).countDistinct(field: keyof IPasswordAuthenticatedUser, criteria?: Criteria<IPasswordAuthenticatedUser>): Promise<number>— Déduplication en mémoire — l’annuaire est déjà entièrement chargé, il n’y a donc pas de parcours à éviter comme en SQL.withTransaction(_tx: ITransaction): IUserRepository— In-memory : pas de transaction — le repository est sa propre unité.findByIdentifier(identifier: string): Promise<IPasswordAuthenticatedUser | null>— Retrouve un utilisateur par son identifiant fonctionnel (email, login…).findBySocialProvider(provider: string, providerId: string): Promise<IPasswordAuthenticatedUser | null>— Retrouve un utilisateur lié à un compte d’un fournisseur OAuth/OIDC.listPage(query: IUserListQuery): Promise<IPage<IPasswordAuthenticatedUser>>— {@inheritDoc IUserRepository.listPage}countUsers(query: IUserListQuery): Promise<number>— {@inheritDoc IUserRepository.countUsers}countActiveAdmins(adminRole: string): Promise<number>— Compte les administrateurs actifs (isActive()et porteurs deadminRole) — garde-fou anti-lockout, calculé au store (SQLCOUNTavec containment de rôle), jamais en chargeant tous les …
MigratingEncoder#
class MigratingEncoder implements IPasswordEncoder
Encodeur composite de migration d’algorithme — accepte les hashs legacy à la vérification, ne produit que des hashs au format courant.
readonly primary: IPasswordEncoder— Encodeur cible — produit tous les nouveaux hashs.readonly legacy: readonly IPasswordEncoder[]— Encodeurs acceptés en lecture seule pendant la migration.constructor(primary: IPasswordEncoder, legacy: readonly IPasswordEncoder[])supports(hash: string): boolean— Reconnaît un hash si l’UN des encodeurs (principal ou legacy) le reconnaît.hash(plain: string): Promise<string>— Hache avec l’encodeur PRINCIPAL uniquement (jamais un format legacy).verify(plain: string, hash: string): Promise<boolean>— Vérifie en routant vers l’encodeur dont le format correspond au hash stocké.needsRehash(hash: string): boolean— Recommande un re-hash si le hash n’est pas au format principal (migration), ou si le principal lui-même le juge obsolète (coûts augmentés).
PasswordPolicy#
class PasswordPolicy implements IPasswordBlocklist
Politique par défaut : six règles, de la moins chère à la plus chère.
readonly options: Required<IPasswordPolicyOptions>constructor(options?: IPasswordPolicyOptions)violation(plain: string, subject?: IPasswordSubjectHint): Promise<string | null>— La règle enfreinte, ounullsi le mot de passe est accepté.isBlocked(plain: string, subject?: IPasswordSubjectHint): Promise<boolean>— Le mot de passe doit-il être refusé ?
UserNotFoundError#
class UserNotFoundError extends nodefonyError
Utilisateur introuvable dans la source d’identité — levée par les méthodes IUserProvider (contrat : jamais null, l’absence d’identité est un échec explicite).
constructor(detail: string)
UserService#
class UserService extends AbstractCrudService<IPasswordAuthenticatedUser, IUserRepository> implements IUserProvider, IPasswordVerifier, IOAuthUserProvisioner
protected readonly encoder: IPasswordEncoderpasswordBlocklist: IPasswordBlocklist | null— Politique de mot de passe (NIST SP 800-63B §5.1.1.2) — consultée à la création et au changement, jamais au login.constructor(repository: IUserRepository, encoder: IPasswordEncoder, ...wiring: ServiceWiring)create(data: PartialInput<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser>— Crée un compte (CRUD hérité), puis émetUSER_CREATED_EVENTet en ATTEND les abonnés.updateOne(criteria: Criteria<IPasswordAuthenticatedUser>, data: PartialInput<IPasswordAuthenticatedUser>): Promise<IPasswordAuthenticatedUser | null>— Met à jour un compte (CRUD hérité).protected beforeUpdate(criteria: Criteria<IPasswordAuthenticatedUser>, data: PartialInput<IPasswordAuthenticatedUser>): Promise<PartialInput<IPasswordAuthenticatedUser>>— Refuse de RENOMMER un compte : sessions, jetons et facteurs sont rangés sousidentifier, le changer les orphelinerait.delete(criteria: Criteria<IPasswordAuthenticatedUser>): Promise<number>— Supprime des comptes (CRUD hérité), un par un, et émetUSER_REVOKED_EVENT(deleted) pour CHAQUE compte effectivement supprimé, en attendant la cascade : sessions, jetons et facteurs (TOTP, passkey …createUser(input: ICreateUserInput): Promise<IPasswordAuthenticatedUser>— Crée un utilisateur — hache le mot de passe en clair s’il est fourni, puis délègue aucreategénérique (hooks + eventonCreated).findByIdentifier(identifier: string): Promise<IPasswordAuthenticatedUser | null>— Charge un utilisateur par son identifiant fonctionnel (email, login…).listPage(query: IUserListQuery): Promise<IPage<IPasswordAuthenticatedUser>>— Liste paginée nativement d’utilisateurs (filtres role/enabled/q) — délègue au repository, qui ne matérialise jamais plus d’une page.sortableFields(): readonly string[]— Champs de tri que le repository actuellement branché sait honorer.countActiveAdmins(adminRole: string): Promise<number>— Compte les administrateurs actifs porteurs deadminRole— garde-fou anti-lockout calculé au store (jamais en chargeant tous les utilisateurs).countUserFacets(adminRole: string, query?: Partial<IUserListQuery>): Promise<IUserCounts>— Les compteurs de tête de la console — posés sur l’annuaire ENTIER, pas sur la page affichée.changePassword(id: string, plainPassword: string): Promise<IPasswordAuthenticatedUser | null>— Change le mot de passe d’un utilisateur — hache le clair avant persistance.authenticate(identifier: string, plain: string): Promise<IPasswordAuthenticatedUser | null>— Authentifie par identifiant + mot de passe.loadUserByIdentifier(identifier: string): Promise<IUser>— {@inheritDoc IUserProvider.loadUserByIdentifier}loadUserByOAuth(provider: string, providerId: string): Promise<IUser>— {@inheritDoc IUserProvider.loadUserByOAuth}refreshUser(user: IUser): Promise<IUser>— {@inheritDoc IUserProvider.refreshUser}provisionOAuthUser(profile: IOAuthProfile, policy: IOAuthProvisionPolicy): Promise<IUser>— {@inheritDoc IOAuthUserProvisioner.provisionOAuthUser}syncOAuthRoles(provider: string, providerId: string, roles: readonly string[]): Promise<IUser>— {@inheritDoc IOAuthUserProvisioner.syncOAuthRoles}
WeakPasswordError#
class WeakPasswordError extends nodefonyError
Mot de passe refusé par la politique (connu-compromis / interdit) — code = 400.
readonly violation: string | null— La règle enfreinte, telle que la politique l’a nommée (nullsi muette).constructor(violation?: string | null)
Fonctions (20)#
assertUserContract#
function assertUserContract(present: Iterable<string>, origin: string, expected?: readonly IUserColumn[]): void
Refuse une entité utilisateur incomplète, en nommant chaque colonne absente ET ce qui la lit.
attachExtraColumns#
function attachExtraColumns<T extends object>(user: T, row: Readonly<Record<string, unknown>>, skip?: ReadonlySet<string>): T
Reporte sur un utilisateur reconstruit toutes les colonnes que BaseUser ne porte pas — horodatages de la ligne, et champs métier ajoutés par l’application.
authenticatedUser#
function authenticatedUser(): IUser | null
L’utilisateur AUTHENTIFIÉ de la requête courante, typé IUser — ou null (hors zone, anonyme, ou principal qui n’est pas un IUser).
createUserAdminApi#
function createUserAdminApi(container: Container): IAdminApi
Producteur IAdminApi du domaine utilisateur — exposé sous /nodefony/user/api/users. Défini DANS @nodefony/user (propriétaire du UserService/IUser) mais enregistré par un module bootable (@nodefony/security, via registerUserAdminApi) car @nodefony/user est une lib pure non-bootable — exactement le cas prévu par le core : un module qui ne dépend que de nodefony produit sa donnée d’admin.
describeSeedFailure#
function describeSeedFailure(cause: unknown, context: ISeedFailureContext): string
Rédige le message d’un semis raté : QUEL compte, QUELLE règle, QUEL geste.
encoderFromConfig#
function encoderFromConfig(specs: readonly IEncoderSpec[]): IPasswordEncoder
Traduit une liste ORDONNÉE de specs d’encodeurs en encodeur exécutable — le pont entre la section encoders de la config sécurité et le UserService.
listUserStores#
function listUserStores(): string[]
Liste des backends utilisateur disponibles — alimente le champ available du statut user (écran Studio « Stores »). "memory" est mis EN TÊTE (baseline builtin, toujours disponible = le repli qui marche partout), les adapters ORM suivent triés. L’ordre est celui affiché dans la colonne « Backends dispo ».
mergeProfileIntoMetadata#
function mergeProfileIntoMetadata(metadata: unknown, patch: Partial<Record<ProfileField, string>>): Record<string, unknown>
Fusionne un patch validé dans la metadata existante en préservant les autres clés. Les champs de profil vidés ("") sont RETIRÉS (pas de clé fantôme). Rend la nouvelle metadata complète, prête pour updateOne({ metadata }).
missingUserColumns#
function missingUserColumns(present: Iterable<string>, expected?: readonly IUserColumn[]): readonly IUserColumn[]
Les colonnes du contrat qu’une définition d’entité ne rend PAS.
profileFromClaims#
function profileFromClaims(claims: Record<string, unknown>): Partial<Record<ProfileField, string>>
Pré-remplit un profil depuis des claims OIDC/OAuth (provisioning JIT d’un Shadow User social). Mappe les claims standard (given_name/family_name/ name/email/picture/locale, + avatar_url GitHub) vers IUserProfile, best-effort par champ : chaque valeur est validée isolément (bornes/format) et un claim invalide est ignoré sans bloquer les autres ni le login. Les claims viennent d’un tiers → lecture défensive.
projectProfile#
function projectProfile(metadata: unknown): IUserProfile
Projette la metadata brute d’une entité vers un IUserProfile — lecture par allowlist (seules les clés connues, typées string non vide). Garantit qu’aucune autre clé de metadata (applicative/sensible) n’entre dans le DTO.
projectProviderRoles#
function projectProviderRoles(metadata: unknown): Record<string, string[]>
Rôles gérés par CHAQUE fournisseur, lus dans metadata — pour l’affichage.
readProviderRoles#
function readProviderRoles(metadata: unknown, provider: string): string[]
Rôles que provider a accordés au dernier calcul, lus dans metadata.
reconcileProviderRoles#
function reconcileProviderRoles(current: readonly string[], previous: readonly string[], next: readonly string[]): IProviderRolesReconciliation
Recalcule l’ensemble effectif : rôles actuels − ceux que le fournisseur gérait, ∪ ceux qu’il accorde maintenant.
registerUserAdminApi#
function registerUserAdminApi(registry: IAdminRegistry, container: Container): void
Enregistre le producteur admin utilisateur sur le broker — idempotent. À appeler au onKernelBoot d’un module bootable qui dépend de @nodefony/user (typiquement @nodefony/security), @nodefony/user n’étant pas lui-même un module.
registerUserStore#
function registerUserStore(name: string): void
Déclare un backend de persistance utilisateur disponible (idempotent).
requestUser#
function requestUser(identifier: string): IUser | null
L’utilisateur DÉJÀ chargé pour la requête courante, s’il est bien celui qu’on cherche — sinon null, et l’appelant relit auprès du fournisseur.
toUserSummary#
function toUserSummary(user: IUser): IUserSummary
Projette un IUser en IUserSummary redacté. Fonction pure (cœur de la garantie anti-fuite, testée isolément) : currentRole/ socialProviders/timestamps sont lus défensivement (présents sur l’entité ORM, absents du contrat strict IUser) — password jamais lu ; de metadata, seules profile (allowlist) et providerRoles (des noms de rôles) passent.
truncatedPasswordHash#
function truncatedPasswordHash(plain: string): number
Les 4 premiers octets du SHA-1, en entier non signé.
validateProfilePatch#
function validateProfilePatch(input: unknown): { ok: true; value: Partial<Record<ProfileField, string>>; } | { ok: false; error: string; }
Valide + normalise un patch de profil reçu d’un client. Allowlist stricte : seules les clés PROFILE_FIELDS sont lues (anti-injection d’une clé metadata arbitraire). Chaque valeur est trimée ; une chaîne vide ou null = effacement du champ (matérialisé "", retiré au merge).
Constantes (12)#
DEFAULT_PASSWORD_POLICY#
const DEFAULT_PASSWORD_POLICY: Required<IPasswordPolicyOptions>
Défauts de la politique — source unique, relue par les tests.
PROVIDER_ROLES_KEY#
const PROVIDER_ROLES_KEY = "providerRoles"
Clé de metadata : { [fournisseur]: rôles accordés au dernier calcul }.
ROLE_ANONYMOUS#
const ROLE_ANONYMOUS = "ROLE_ANONYMOUS"
Rôle unique d’un utilisateur non authentifié.
USER_COLUMNS#
const USER_COLUMNS: readonly IUserColumn[]
USER_CREATED_EVENT#
const USER_CREATED_EVENT = "onUserCreated"
Événement kernel — un compte vient d’être créé (charge utile IUserCreatedEvent). Émis par UserService.create et attendu : @nodefony/security y retire les facteurs (TOTP, passkeys) laissés sous le même identifiant par un ancien titulaire, et une connexion immédiate ne doit pas les trouver encore là.
USER_DEFAULT_ORDER#
const USER_DEFAULT_ORDER: NonNullable<IPageQuery["order"]>
Ordre appliqué quand le client n’en demande aucun : par identifiant croissant — le seul champ toujours présent et unique, donc le seul qui rende une pagination offset déterministe sans départage supplémentaire.
USER_REVOKED_EVENT#
const USER_REVOKED_EVENT = "onUserRevoked"
Événement kernel — l’accès d’un compte doit être révoqué partout (suppression, désactivation, verrouillage, changement de mot de passe). Point d’extension : un module qui possède des artefacts liés à un compte (sessions, jetons, webhooks…) s’y abonne et nettoie LES SIENS — zéro couplage avec @nodefony/user. Émis par UserService seul, et attendu.
USER_SORTABLE_FIELDS#
const USER_SORTABLE_FIELDS: readonly [ "identifier", "enabled", "createdAt", "updatedAt", "id" ]
Le vocabulaire de tri des utilisateurs — source unique, en noms publics.
USER_SORTABLE_FIELDS_COMMON#
const USER_SORTABLE_FIELDS_COMMON: readonly [ "identifier", "enabled", "id" ]
Socle garanti par tous les backends d’utilisateurs. C’est ce sur quoi une interface peut compter sans savoir quelle base est branchée.
USER_SORTABLE_FIELDS_IN_MEMORY#
const USER_SORTABLE_FIELDS_IN_MEMORY: readonly [ "identifier", "enabled", "id" ]
Sous-ensemble réellement triable par l’annuaire en mémoire.
USER_TABLE_NAME#
const USER_TABLE_NAME = "User"
Le nom de la TABLE (ou collection) qui porte les utilisateurs.
anonymousUser#
const anonymousUser: AnonymousUser
Singleton d’AnonymousUser — instance partagée et gelée à réutiliser à chaque requête non authentifiée (zéro allocation dans le hot path).
Interfaces (26)#
Argon2idOptions#
interface Argon2idOptions
Paramètres de coût Argon2id (RFC 9106).
memoryKiB?: number— Mémoire par hash en KiB (défaut 19456 = 19 MiB, minimum OWASP).timeCost?: number— Nombre de passes sur la mémoire (défaut 3 — voir DEFAULT_TIME_COST).parallelism?: number— Nombre de threads/lanes (défaut 1 — chaque lane allouememoryKiB).
IBaseUserOptions#
interface IBaseUserOptions
Options de construction d’un BaseUser — signature en objet (lisibilité + extensibilité).
id: string— Identifiant interne (UUID).identifier: string— Identifiant fonctionnel (email, login…).roles?: string[]— Rôles plats accordés (copiés défensivement).password?: string | null— Hash du mot de passe local, ounull(compte OAuth-only).enabled?: boolean— Compte activé.locked?: boolean— Compte verrouillé.currentRole?: string | null— Profil de rôle actif en session.socialProviders?: ISocialProvider[]— Comptes externes liés (OAuth/OIDC).metadata?: Record<string, unknown>— Métadonnées applicatives libres.credentialsVersion?: number | null— Version des identifiants (cfIUser.credentialsVersion).
ICreateUserInput#
interface ICreateUserInput
Données d’entrée de création d’un utilisateur — le mot de passe est fourni en clair puis haché par UserService.createUser (jamais persisté tel quel).
identifier: string— Identifiant fonctionnel (email, login…).plainPassword?: string | null— Mot de passe en clair, ounull/absent pour un compte sans credential local.roles?: string[]— Rôles plats initiaux.
IEncoderSpec#
interface IEncoderSpec
Spécification déclarative d’UN encodeur de mot de passe — miroir structurel de la section encoders du schéma Zod de @nodefony/security (qui valide bornes et défauts), SANS en dépendre : ce module reste la couche basse, l’inversion de dépendance est préservée (security consomme user, jamais l’inverse).
type: "argon2id" | "bcrypt"— Algorithme :argon2id(RFC 9106, défaut) oubcrypt(legacy).memoryKiB?: number— Argon2id : mémoire par hash (KiB).timeCost?: number— Argon2id : passes d’itération.parallelism?: number— Argon2id : lanes parallèles.rounds?: number— bcrypt : coût (ignoré par argon2id).
IOAuthProfile#
interface IOAuthProfile
Profil d’identité normalisé extrait d’un fournisseur OAuth/OIDC.
readonly provider: string— Fournisseur ("google","github"…).readonly providerId: string— Identifiant stable du compte chez le fournisseur (subOIDC,idGitHub).readonly email: string | null— Email retourné par le fournisseur, ounull(compte sans email exposé).readonly emailVerified: boolean—truesi le fournisseur certifie l’email vérifié.readonly name: string | null— Nom d’affichage, ounull.readonly raw: Record<string, unknown>— Charge utile brute du fournisseur (claims / payload) — pour un provisioner custom.
IOAuthProvisionPolicy#
interface IOAuthProvisionPolicy
Politique de provisioning décidée par l’appelant (config oauth2 de @nodefony/security) et transmise au provisioner — celui-ci ne lit aucune config, il applique ce qu’on lui passe (un provisioner applicatif peut ignorer ces valeurs et appliquer sa propre logique).
readonly defaultRoles: string[]— Rôles plats accordés au Shadow User à la création uniquement.readonly allowSignup: boolean—true: créer une ligne locale au premier login externe (JIT).readonly providerRoles?: readonly string[]— Rôles que le fournisseur accorde MAINTENANT, déjà traduits en rôles de l’application (roleMappingde@nodefony/security).
IOAuthUserProvisioner#
interface IOAuthUserProvisioner
Capability de provisioning d’un utilisateur OAuth — pattern Shadow User Just-In-Time.
provisionOAuthUser(profile: IOAuthProfile, policy: IOAuthProvisionPolicy): Promise<IUser>— Retourne l’utilisateur lié au compte externe, en le créant si absent (selonpolicy.allowSignup).syncOAuthRoles?(provider: string, providerId: string, roles: readonly string[]): Promise<IUser>— Recalcule les rôles gérés par un fournisseur pour le compte qui lui est lié — appelé à chaque jeton d’API, sans passer par une connexion.
IPasswordAuthenticatedUser#
interface IPasswordAuthenticatedUser extends IUser
Utilisateur porteur d’un credential mot de passe local — extension de IUser.
readonly password: string | null— Hash du mot de passe stocké, ounullpour un compte sans mot de passe local.
IPasswordBlocklist#
interface IPasswordBlocklist
Contrat de liste de blocage de mots de passe compromis (NIST SP 800-63B §5.1.1.2) — consulté à la CRÉATION et au CHANGEMENT de mot de passe, jamais au login (le hash stocké ne permet plus de juger le clair, et refuser un login existant verrouillerait l’utilisateur).
isBlocked(plain: string, subject?: IPasswordSubjectHint): Promise<boolean>— Le mot de passe en clair est-il connu-compromis / interdit ?violation?(plain: string, subject?: IPasswordSubjectHint): Promise<string | null>— La règle enfreinte, en français, ounullsi le mot de passe est accepté.
IPasswordEncoder#
interface IPasswordEncoder
Contrat d’un encodeur de mot de passe — abstraction de l’algorithme de hachage.
supports(hash: string): boolean— Indique si un hash stocké est au format de CET encodeur (parsing pur, sync).hash(plain: string): Promise<string>— Hache un mot de passe en clair (sel inclus dans la sortie).verify(plain: string, hash: string): Promise<boolean>— Vérifie qu’un mot de passe en clair correspond à un hash stocké.needsRehash(hash: string): boolean— Indique si un hash devrait être recalculé (paramètres de coût obsolètes).
IPasswordPolicyOptions#
interface IPasswordPolicyOptions
Réglages d’une politique — tout est optionnel, les défauts sont sains.
minLength?: number— Longueur minimale acceptée.blocklist?: readonly string[]— Mots de passe refusés en propre (noms métier, du produit, du client).blocklistFile?: string | null— Fichier de mots de passe refusés, une valeur par ligne (UTF-8).checkCommonPasswords?: boolean— Consulter les empreintes embarquées.
IPasswordSubjectHint#
interface IPasswordSubjectHint
Ce qu’un appelant peut dire du compte visé — tout est optionnel.
identifier?: string— Identifiant du compte (courriel, login).
IPasswordVerifier#
interface IPasswordVerifier
Contrat de vérification d’un credential mot de passe — le guichet auquel @nodefony/security présente un couple identifiant/mot de passe et qui répond par un verdict, jamais par un hash.
authenticate(identifier: string, plain: string): Promise<IUser | null>— Vérifie un couple identifiant/mot de passe.
IProviderRolesReconciliation#
interface IProviderRolesReconciliation
Résultat d’un recalcul.
readonly roles: string[]— Ensemble effectif à écrire dansroles.readonly changed: boolean—truesirolesOU la trace des rôles gérés doit être réécrite.
ISeedFailureContext#
interface ISeedFailureContext
Ce que l’appelant sait du semis, et que l’erreur ignore.
identifier: string— Identifiant du compte qu’on tentait de semer ("admin").envVar: string— Variable d’environnement qui porte le mot de passe ("NF_ADMIN_PASSWORD").fromEnv: boolean— Le mot de passe venait-il deenvVar?admin?: boolean— Le compte visait-il un rôle d’administration ?
ISocialProvider#
interface ISocialProvider
Référence à un compte d’un fournisseur d’identité externe (OAuth / OIDC).
readonly provider: string— Identifiant du fournisseur ("google","github","microsoft"…).readonly providerId: string— Identifiant du compte chez le fournisseur.readonly createdAt: Date— Date de liaison du compte.
IUser#
interface IUser
Contrat strict d’un utilisateur Nodefony — surface minimale garantie au framework.
readonly id: string— Identifiant interne — UUID (jamaisstring | number).readonly identifier: string— Identifiant fonctionnel d’authentification (email, login…).readonly roles: string[]— Rôles plats accordés (sans hiérarchie résolue).hasRole(role: string): boolean— Indique si l’utilisateur possède le rôle exact donné (sans hiérarchie).isActive(): boolean— Indique si le compte est actif (activé et non expiré).isLocked(): boolean— Indique si le compte est verrouillé (ex.readonly credentialsVersion?: number | null— Version des identifiants du compte, incrémentée à chaque changement de mot de passe — absente ounullvaut 0.
IUserColumn#
interface IUserColumn
Une colonne du contrat utilisateur : son nom, ce qu’elle contient, et qui la lit.
readonly name: string— Nom de la colonne, identique sur tous les moteurs (figé en v1).readonly type: UserColumnType— Ce que la colonne contient, indépendamment du moteur.readonly nullable: boolean—truesi la colonne accepte l’absence de valeur.readonly unique?: boolean—truesi la valeur doit être unique dans l’annuaire (implique un index).readonly origin: UserColumnOrigin— Qui fournit la valeur — cfUserColumnOrigin.readonly makeDefault?: () => unknown— Fabrique du défaut, appelée à CHAQUE insertion.readonly refreshedOnWrite?: boolean—truesi la valeur est régénérée à CHAQUE écriture (horodatage de modification).readonly readers: readonly string[]— Les lecteurs qui cassent si la colonne manque — nommés dans les refus.readonly description: string— Rôle de la colonne, en une phrase.
IUserCreatedEvent#
interface IUserCreatedEvent
Charge utile de USER_CREATED_EVENT.
readonly id: string—IUser.iddu compte créé.readonly identifier: string—IUser.identifier— clé sous laquelle ses facteurs seront rangés.
IUserListQuery#
interface IUserListQuery extends IPageQuery
Requête de listing paginé d’utilisateurs — le contrat de page standard du core (IPageQuery) enrichi des filtres propres à l’utilisateur.
role?: string— Rôle plat devant figurer dansroles(containment natif).enabled?: boolean— Restreint à l’état actif (isActive()).locked?: boolean— Restreint aux comptes verrouillés (isLocked()), ou aux non verrouillés.hasSocial?: boolean— Restreint aux comptes liés à au moins un fournisseur d’identité externe (OAuth), ou à ceux qui n’en ont aucun.
IUserProfile#
interface IUserProfile
Profil public d’un utilisateur — sous-ensemble des standard claims OpenID Connect (OIDC §5.1) en camelCase (convention Nodefony). Stocké dans BaseUser.metadata.profile, PAS dans des colonnes dédiées : IUser reste identité + rôles (le profil = donnée d’affichage anti-migration). Exposé par allowlist dans le DTO admin (IUserSummary.profile) — les autres clés de metadata (applicatives, potentiellement sensibles) ne fuitent jamais.
givenName?: string— Prénom — OIDCgiven_name.familyName?: string— Nom de famille — OIDCfamily_name.displayName?: string— Nom affiché — OIDCname(sinon dérivable « givenName familyName »).email?: string— Adresse e-mail de contact — OIDCemail(distincte de l’identifier).locale?: string— Préférence de langue — OIDClocale(BCP 47, ex.picture?: string— URL d’avatar — OIDCpicture(http/https).
IUserProvider#
interface IUserProvider
Contrat de fourniture d’utilisateurs — la source d’identité (DB, LDAP, SSO…).
loadUserByIdentifier(identifier: string): Promise<IUser>— Charge un utilisateur par son identifiant fonctionnel (email, login…).loadUserByOAuth(provider: string, providerId: string): Promise<IUser>— Charge un utilisateur lié à un compte d’un fournisseur OAuth/OIDC.refreshUser(user: IUser): Promise<IUser>— Recharge un utilisateur depuis la source (rôles/état à jour) à chaque requête.
IUserRepository#
interface IUserRepository extends IRepository<IPasswordAuthenticatedUser>, ISortableSource
Repository spécialisé utilisateur — IRepository<IPasswordAuthenticatedUser> enrichi de finders métier.
findByIdentifier(identifier: string): Promise<IPasswordAuthenticatedUser | null>— Retrouve un utilisateur par son identifiant fonctionnel (email, login…).findBySocialProvider(provider: string, providerId: string): Promise<IPasswordAuthenticatedUser | null>— Retrouve un utilisateur lié à un compte d’un fournisseur OAuth/OIDC.listPage(query: IUserListQuery): Promise<IPage<IPasswordAuthenticatedUser>>— Liste paginée NATIVEMENT d’utilisateurs — ne matérialise jamais plus d’une page en mémoire (règle perf/mémoire absolue de Nodefony).countActiveAdmins(adminRole: string): Promise<number>— Compte les administrateurs actifs (isActive()et porteurs deadminRole) — garde-fou anti-lockout, calculé au store (SQLCOUNTavec containment de rôle), jamais en chargeant tous les …countUsers(query: IUserListQuery): Promise<number>— Compte les comptes correspondant aux filtres, sans les énumérer.
IUserRevokedEvent#
interface IUserRevokedEvent
Charge utile de USER_REVOKED_EVENT. identifier = clé de jointure des artefacts (session user, PAT subjectId). tenantId = slot multi-tenant (toujours null en mono-tenant — réserve coût-0 pour une cascade scopée).
id: stringidentifier: stringtenantId: string | nullreason: "deleted" | "disabled" | "locked" | "password_changed"— Ce qui a coupé l’accès du porteur.
IUserRow#
interface IUserRow
Forme plate d’un utilisateur tel qu’un dépôt le rend, avant reconstruction en BaseUser — pendant TypeScript de USER_COLUMNS.
id: stringidentifier: stringpassword: string | nullroles: string[]enabled: booleanlocked: booleancurrentRole: string | nullsocialProviders: ISocialProvider[]metadata: Record<string, unknown>credentialsVersion: number | nullcreatedAt: DateupdatedAt: Date
IUserSummary#
interface IUserSummary
Projection publique d’un utilisateur pour l’ADMINISTRATION (Studio, P6.15). Redaction PAR CONSTRUCTION (allowlist) — ne porte jamais password, jamais metadata (peut contenir du sensible), et les liens sociaux sont exposés sans jeton (provider/providerId/createdAt seulement).
id: stringidentifier: stringroles: string[]enabled: boolean— Compte actif (isActive()), pilotable via PATCHenabled.locked: boolean— Compte verrouillé (isLocked()), pilotable via PATCHlocked.hasPassword: boolean—truesi le compte a un mot de passe LOCAL (par opposition à OAuth-only).currentRole: string | null— Profil de rôle actif en session (P5.11), ounull.socialProviders: { provider: string; providerId: string; createdAt: number | null; }[]— Comptes externes liés — jamais de jeton, seulement la référence.profile: IUserProfile— Profil d’affichage (claims OIDC : prénom/nom/email/locale/avatar), lu par allowlist depuismetadata.profile— jamais les autres clés demetadata.providerRoles: Record<string, string[]>— Rôles GÉRÉS par un fournisseur d’identité (roleMapping), par fournisseur — sous-ensemble derolesrecalculé à chaque connexion.createdAt: number | null— Création (epoch ms) si l’entité la porte (ORM), sinonnull.updatedAt: number | null— Dernière mise à jour (epoch ms) si connue, sinonnull.tenantId: string | null— Réserve multi-tenant (toujoursnullen mono-tenant — slot coût-0).
Types (3)#
AuthFailureReason#
type AuthFailureReason = "unknown_identifier" | "disabled" | "locked" | "no_password" | "bad_credentials"
Raison d’un échec d’authentification (émise avec onAuthenticationFailure).
UserColumnOrigin#
type UserColumnOrigin = "identity" | "column" | "audit"
D’où vient la valeur d’une colonne — ce qui décide si un adaptateur doit la DÉCLARER ou peut la laisser au moteur.
UserColumnType#
type UserColumnType = "uuid" | "string" | "string[]" | "integer" | "boolean" | "object" | "object[]" | "date"
Type logique d’une colonne de l’utilisateur — ce que la donnée EST, jamais comment un moteur la range.