feat(shared): schéma et vues pour la création de comptes par un admin
`adminCreateUserSchema` (prénom/nom/email, sans mot de passe — généré côté serveur) + les vues `AdminUserListItemView` / `AdminUserCreatedView` consommées par `POST`/`GET /admin/api/users`. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d1430498e0
commit
9123f6358e
2 changed files with 49 additions and 0 deletions
|
|
@ -17,6 +17,24 @@ export const adminLoginSchema = z.object({
|
||||||
/** Inferred TS type for {@link adminLoginSchema}'s validated output. */
|
/** Inferred TS type for {@link adminLoginSchema}'s validated output. */
|
||||||
export type AdminLoginInput = z.infer<typeof adminLoginSchema>;
|
export type AdminLoginInput = z.infer<typeof adminLoginSchema>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Payload accepted by `POST /admin/api/users` — an operator provisioning an
|
||||||
|
* end-user account by hand (test accounts, pre-registration, support). Its
|
||||||
|
* own contract, not a re-export of `signupSchema` (same stance as
|
||||||
|
* {@link adminLoginSchema} vs `loginSchema`), and notably **without a
|
||||||
|
* `password` field**: the server generates a one-time temporary password
|
||||||
|
* and returns it once (see `apps/api`'s `admin-users.service.ts`). The
|
||||||
|
* name/email rules mirror `signupSchema` so a hand-created account is
|
||||||
|
* indistinguishable from a self-signed-up one afterwards.
|
||||||
|
*/
|
||||||
|
export const adminCreateUserSchema = z.object({
|
||||||
|
firstName: z.string().trim().min(1, "Le prénom est requis").max(100),
|
||||||
|
lastName: z.string().trim().min(1, "Le nom est requis").max(100),
|
||||||
|
email: z.string().trim().toLowerCase().email("Email invalide"),
|
||||||
|
});
|
||||||
|
/** Inferred TS type for {@link adminCreateUserSchema}'s validated output. */
|
||||||
|
export type AdminCreateUserInput = z.infer<typeof adminCreateUserSchema>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query params for `GET /admin/api/metrics` — `?days=` bounds how far back the
|
* Query params for `GET /admin/api/metrics` — `?days=` bounds how far back the
|
||||||
* time-series go (and how many daily buckets they carry). Coerced from the
|
* time-series go (and how many daily buckets they carry). Coerced from the
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,37 @@ export interface AdminUserView {
|
||||||
lastLoginAt: string | null;
|
lastLoginAt: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* One row of `GET /admin/api/users` — an end-user account as shown in the
|
||||||
|
* admin's user list. Declared by hand rather than derived from the Prisma
|
||||||
|
* `UserProfile` type (same reason as {@link AdminUserView} / {@link
|
||||||
|
* SafeUserProfile}: apps/web must not depend on `@prisma/client`), and
|
||||||
|
* deliberately *not* {@link SafeUserProfile}: this view drops `tokenVersion`
|
||||||
|
* (internal) and adds `householdName` (resolved server-side) + `createdAt`.
|
||||||
|
* `householdName` is `null` when the account belongs to no household;
|
||||||
|
* `createdAt` is an ISO 8601 string.
|
||||||
|
*/
|
||||||
|
export interface AdminUserListItemView {
|
||||||
|
id: number;
|
||||||
|
firstName: string;
|
||||||
|
lastName: string;
|
||||||
|
email: string;
|
||||||
|
householdName: string | null;
|
||||||
|
createdAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response of `POST /admin/api/users`. Carries the freshly-created account
|
||||||
|
* plus the **one-time** temporary password the server generated for it —
|
||||||
|
* never stored in plain text, never retrievable again, so the operator must
|
||||||
|
* copy it now and relay it to the user out of band.
|
||||||
|
*/
|
||||||
|
export interface AdminUserCreatedView {
|
||||||
|
user: AdminUserListItemView;
|
||||||
|
/** Plain-text temporary password, shown exactly once. */
|
||||||
|
temporaryPassword: string;
|
||||||
|
}
|
||||||
|
|
||||||
/** One `{ key, count }` breakdown row — e.g. recipes per source, corrections per status. */
|
/** One `{ key, count }` breakdown row — e.g. recipes per source, corrections per status. */
|
||||||
export interface MetricsBreakdownRow {
|
export interface MetricsBreakdownRow {
|
||||||
key: string;
|
key: string;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue