feat(auth): add user invitation flow with account setup

- add `createAccountSetup`, `verifyAccountSetupToken`, `deleteAccountSetupToken` to verifications core
- add `completeAccountSetup` function to auth core for password creation on invite
- add `InvitationEmail` template for sending invite links
- add `SetupAccountPage` client page for invited users to set their password
- add `UserCreateModal` admin component to invite new users
- wire invitation action and API endpoint in auth feature
- update admin `UsersPage` to include user creation modal
- update auth and admin README docs
This commit is contained in:
2026-04-25 09:03:15 -04:00
parent 96c8cf1e97
commit abd9d651dc
16 changed files with 681 additions and 21 deletions
@@ -0,0 +1,35 @@
import { Button, Section, Text, Link } from "@react-email/components";
import { BaseLayout } from "@zen/core/email/templates";
export const InvitationEmail = ({ setupUrl, companyName }) => (
<BaseLayout
preview={`Terminez la création de votre compte ${companyName}`}
title="Bienvenue — créez votre mot de passe"
companyName={companyName}
supportSection={true}
>
<Text className="text-[14px] leading-[24px] text-neutral-600 mt-[4px] mb-[24px]">
Un administrateur a créé un compte pour vous sur <span className="font-medium text-neutral-900">{companyName}</span>. Cliquez sur le bouton ci-dessous pour choisir votre mot de passe et accéder à votre compte.
</Text>
<Section className="mt-[28px] mb-[32px]">
<Button
href={setupUrl}
className="bg-neutral-900 rounded-[8px] text-white font-medium px-[20px] py-[11px] no-underline text-[13px]"
>
Créer mon mot de passe
</Button>
</Section>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0">
Ce lien expire dans 48 heures. Si vous n'attendiez pas cette invitation, ignorez ce message.
</Text>
<Text className="text-[12px] leading-[20px] text-neutral-400 m-0 mt-[8px]">
Lien :{' '}
<Link href={setupUrl} className="text-neutral-400 underline break-all">
{setupUrl}
</Link>
</Text>
</BaseLayout>
);