feat(entities/user): access.ts (copie backend) + lib.ts (hasAccess/canSimulate) + 37 tests
This commit is contained in:
parent
94731edafc
commit
ef9a84433e
4 changed files with 421 additions and 0 deletions
73
src/entities/user/lib.ts
Normal file
73
src/entities/user/lib.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* Alias frontend-idiomatiques pour les fonctions d'accès.
|
||||
*
|
||||
* Ce fichier est la PORTE D'ENTRÉE pour tout code frontend qui vérifie
|
||||
* une permission ou un quota. Ne JAMAIS importer directement depuis access.ts
|
||||
* dans les composants ou les hooks.
|
||||
*
|
||||
* Cf. ADR 005 pour la justification des alias et ADR 004 pour la règle
|
||||
* de synchronisation de access.ts avec le backend.
|
||||
*/
|
||||
|
||||
import {
|
||||
canUserSimulate,
|
||||
checkFeatureAccess,
|
||||
getPlanPermissions,
|
||||
type Feature,
|
||||
type Plan,
|
||||
} from './access'
|
||||
|
||||
/**
|
||||
* Vérifie si un plan a accès à une feature booléenne donnée.
|
||||
*
|
||||
* Alias idiomatique React de `checkFeatureAccess` (backend).
|
||||
* La feature 'basic_report' est toujours autorisée (tous plans).
|
||||
*
|
||||
* @example
|
||||
* if (hasAccess(plan, 'exam_mode')) { ... }
|
||||
* if (hasAccess(plan, 'oral_t2_live')) { ... }
|
||||
*
|
||||
* @param plan - Plan de l'utilisateur ('free' | 'standard' | 'premium')
|
||||
* @param feature - Nom de la feature à vérifier
|
||||
* @returns true si le plan donne accès à la feature
|
||||
*/
|
||||
export const hasAccess = checkFeatureAccess
|
||||
|
||||
/**
|
||||
* Résultat d'un check de simulation.
|
||||
*/
|
||||
export interface SimulationCheck {
|
||||
allowed: boolean
|
||||
reason?: 'quota_reached' | 'invalid_plan' | string
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un utilisateur peut lancer une nouvelle simulation.
|
||||
*
|
||||
* Alias idiomatique de `canUserSimulate` (backend) avec une signature
|
||||
* plus ergonomique côté frontend : prend `plan` et `simulationsUsed`
|
||||
* séparément au lieu d'un objet `user`.
|
||||
*
|
||||
* @example
|
||||
* const { allowed, reason } = canSimulate(plan, simulationsUsed)
|
||||
* if (!allowed) {
|
||||
* if (reason === 'quota_reached') openUpgradeModal()
|
||||
* }
|
||||
*
|
||||
* @param plan - Plan de l'utilisateur
|
||||
* @param simulationsUsed - Nombre de simulations déjà consommées
|
||||
* @returns Objet `{ allowed, reason? }`
|
||||
*/
|
||||
export function canSimulate(plan: string, simulationsUsed: number): SimulationCheck {
|
||||
return canUserSimulate({ plan, simulations_used: simulationsUsed })
|
||||
}
|
||||
|
||||
/**
|
||||
* Ré-export direct — pas d'alias car le nom est déjà idiomatique.
|
||||
*/
|
||||
export { getPlanPermissions }
|
||||
|
||||
/**
|
||||
* Ré-export des types pour les consommateurs.
|
||||
*/
|
||||
export type { Feature, Plan }
|
||||
Loading…
Add table
Add a link
Reference in a new issue