AuthTemplatesValidation.tsx384 lines · main
1import * as z from 'zod'
2
3import type { AuthTemplate, TemplateVariable, TemplateVariableName } from './EmailTemplates.types'
4
5const TemplateVariables: Record<TemplateVariableName, TemplateVariable> = {
6 ConfirmationURL: {
7 name: 'ConfirmationURL',
8 value: '{{ .ConfirmationURL }}',
9 description: 'URL to confirm the email address for the new account',
10 },
11 Token: {
12 name: 'Token',
13 value: '{{ .Token }}',
14 description: '6-digit numeric email OTP',
15 },
16 TokenHash: {
17 name: 'TokenHash',
18 value: '{{ .TokenHash }}',
19 description: 'Hashed token used in the URL, useful for constructing your own email link',
20 },
21 SiteURL: {
22 name: 'SiteURL',
23 value: '{{ .SiteURL }}',
24 description: 'Redirect URL',
25 },
26 Email: {
27 name: 'Email',
28 value: '{{ .Email }}',
29 description: "User's current email address",
30 },
31 NewEmail: {
32 name: 'NewEmail',
33 value: '{{ .NewEmail }}',
34 description: "User's new email address",
35 },
36 OldEmail: {
37 name: 'OldEmail',
38 value: '{{ .OldEmail }}',
39 description: "User's old email address",
40 },
41 Phone: {
42 name: 'Phone',
43 value: '{{ .Phone }}',
44 description: "User's new phone number",
45 },
46 OldPhone: {
47 name: 'OldPhone',
48 value: '{{ .OldPhone }}',
49 description: "User's old phone number",
50 },
51 Provider: {
52 name: 'Provider',
53 value: '{{ .Provider }}',
54 description: 'Provider of newly linked/unlinked identity',
55 },
56 FactorType: {
57 name: 'FactorType',
58 value: '{{ .FactorType }}',
59 description: 'Type of newly enrolled/unenrolled MFA factor',
60 },
61 Data: {
62 name: 'Data',
63 value: '{{ .Data }}',
64 description: (
65 <>
66 User's <code className="text-code-inline">user_metadata</code>, use this to personalize the
67 message
68 </>
69 ),
70 },
71 RedirectTo: {
72 name: 'RedirectTo',
73 value: '{{ .RedirectTo }}',
74 description: (
75 <>
76 Redirect URL passed as the <code className="text-code-inline">redirectTo</code> option in
77 the auth method call
78 </>
79 ),
80 },
81}
82
83const CONFIRMATION: AuthTemplate = {
84 id: 'CONFIRMATION',
85 type: 'object',
86 title: 'Confirm sign up',
87 purpose: 'Ask users to confirm their email address after signing up',
88 properties: {
89 MAILER_SUBJECTS_CONFIRMATION: { title: 'Subject', type: 'string' },
90 MAILER_TEMPLATES_CONFIRMATION_CONTENT: { title: 'Body', type: 'code' },
91 },
92 variables: [
93 TemplateVariables.ConfirmationURL,
94 TemplateVariables.Token,
95 TemplateVariables.TokenHash,
96 TemplateVariables.SiteURL,
97 TemplateVariables.Email,
98 TemplateVariables.Data,
99 TemplateVariables.RedirectTo,
100 ],
101 validationSchema: z.object({
102 MAILER_SUBJECTS_CONFIRMATION: z.string().min(1, 'Subject is required.'),
103 }),
104 misc: {
105 emailTemplateType: 'authentication',
106 },
107}
108
109const INVITE: AuthTemplate = {
110 id: 'INVITE',
111 type: 'object',
112 title: 'Invite user',
113 purpose: "Invite users who don't yet have an account to sign up",
114 properties: {
115 MAILER_SUBJECTS_INVITE: { title: 'Subject', type: 'string' },
116 MAILER_TEMPLATES_INVITE_CONTENT: { title: 'Body', type: 'code' },
117 },
118 variables: [
119 TemplateVariables.ConfirmationURL,
120 TemplateVariables.Token,
121 TemplateVariables.TokenHash,
122 TemplateVariables.SiteURL,
123 TemplateVariables.Email,
124 TemplateVariables.Data,
125 TemplateVariables.RedirectTo,
126 ],
127 validationSchema: z.object({
128 MAILER_SUBJECTS_INVITE: z.string().min(1, 'Subject is required.'),
129 }),
130 misc: {
131 emailTemplateType: 'authentication',
132 },
133}
134
135const MAGIC_LINK: AuthTemplate = {
136 id: 'MAGIC_LINK',
137 type: 'object',
138 title: 'Magic link or OTP',
139 purpose: 'Send a one-time sign-in link or one-time password',
140 properties: {
141 MAILER_SUBJECTS_MAGIC_LINK: { title: 'Subject', type: 'string' },
142 MAILER_TEMPLATES_MAGIC_LINK_CONTENT: { title: 'Body', type: 'code' },
143 },
144 variables: [
145 TemplateVariables.ConfirmationURL,
146 TemplateVariables.Token,
147 TemplateVariables.TokenHash,
148 TemplateVariables.SiteURL,
149 TemplateVariables.Email,
150 TemplateVariables.Data,
151 TemplateVariables.RedirectTo,
152 ],
153 validationSchema: z.object({
154 MAILER_SUBJECTS_MAGIC_LINK: z.string().min(1, 'Subject is required.'),
155 }),
156 misc: {
157 emailTemplateType: 'authentication',
158 },
159}
160
161const EMAIL_CHANGE: AuthTemplate = {
162 id: 'EMAIL_CHANGE',
163 type: 'object',
164 title: 'Change email address',
165 purpose: 'Ask users to verify their new email address after changing it',
166 properties: {
167 MAILER_SUBJECTS_EMAIL_CHANGE: { title: 'Subject', type: 'string' },
168 MAILER_TEMPLATES_EMAIL_CHANGE_CONTENT: { title: 'Body', type: 'code' },
169 },
170 variables: [
171 TemplateVariables.ConfirmationURL,
172 TemplateVariables.Token,
173 TemplateVariables.TokenHash,
174 TemplateVariables.SiteURL,
175 TemplateVariables.Email,
176 TemplateVariables.NewEmail,
177 TemplateVariables.Data,
178 TemplateVariables.RedirectTo,
179 ],
180 validationSchema: z.object({
181 MAILER_SUBJECTS_EMAIL_CHANGE: z.string().min(1, 'Subject is required.'),
182 }),
183 misc: {
184 emailTemplateType: 'authentication',
185 },
186}
187
188const RECOVERY: AuthTemplate = {
189 id: 'RECOVERY',
190 type: 'object',
191 title: 'Reset password',
192 purpose: 'Allow users to reset their password if they forget it',
193 properties: {
194 MAILER_SUBJECTS_RECOVERY: { title: 'Subject', type: 'string' },
195 MAILER_TEMPLATES_RECOVERY_CONTENT: { title: 'Body', type: 'code' },
196 },
197 variables: [
198 TemplateVariables.ConfirmationURL,
199 TemplateVariables.Token,
200 TemplateVariables.TokenHash,
201 TemplateVariables.SiteURL,
202 TemplateVariables.Email,
203 TemplateVariables.Data,
204 TemplateVariables.RedirectTo,
205 ],
206 validationSchema: z.object({
207 MAILER_SUBJECTS_RECOVERY: z.string().min(1, 'Subject is required.'),
208 }),
209 misc: {
210 emailTemplateType: 'authentication',
211 },
212}
213
214const REAUTHENTICATION: AuthTemplate = {
215 id: 'REAUTHENTICATION',
216 type: 'object',
217 title: 'Reauthentication',
218 purpose: 'Ask users to re-authenticate before performing a sensitive action',
219 properties: {
220 MAILER_SUBJECTS_REAUTHENTICATION: { title: 'Subject', type: 'string' },
221 MAILER_TEMPLATES_REAUTHENTICATION_CONTENT: { title: 'Body', type: 'code' },
222 },
223 variables: [
224 TemplateVariables.Token,
225 TemplateVariables.SiteURL,
226 TemplateVariables.Email,
227 TemplateVariables.Data,
228 ],
229 validationSchema: z.object({
230 MAILER_SUBJECTS_REAUTHENTICATION: z.string().min(1, 'Subject is required.'),
231 }),
232 misc: {
233 emailTemplateType: 'authentication',
234 },
235}
236
237// Notifications
238const PASSWORD_CHANGED_NOTIFICATION: AuthTemplate = {
239 id: 'PASSWORD_CHANGED_NOTIFICATION',
240 type: 'object',
241 title: 'Password changed',
242 purpose: 'Notify users when their password has changed',
243 properties: {
244 MAILER_SUBJECTS_PASSWORD_CHANGED_NOTIFICATION: { title: 'Subject', type: 'string' },
245 MAILER_TEMPLATES_PASSWORD_CHANGED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
246 },
247 variables: [TemplateVariables.Email, TemplateVariables.Data],
248 validationSchema: z.object({
249 MAILER_SUBJECTS_PASSWORD_CHANGED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
250 }),
251 misc: {
252 emailTemplateType: 'security',
253 },
254}
255
256const EMAIL_CHANGED_NOTIFICATION: AuthTemplate = {
257 id: 'EMAIL_CHANGED_NOTIFICATION',
258 type: 'object',
259 title: 'Email address changed',
260 purpose: 'Notify users when their email address has changed',
261 properties: {
262 MAILER_SUBJECTS_EMAIL_CHANGED_NOTIFICATION: { title: 'Subject', type: 'string' },
263 MAILER_TEMPLATES_EMAIL_CHANGED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
264 },
265 variables: [TemplateVariables.Email, TemplateVariables.OldEmail, TemplateVariables.Data],
266 validationSchema: z.object({
267 MAILER_SUBJECTS_EMAIL_CHANGED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
268 }),
269 misc: {
270 emailTemplateType: 'security',
271 },
272}
273
274const PHONE_CHANGED_NOTIFICATION: AuthTemplate = {
275 id: 'PHONE_CHANGED_NOTIFICATION',
276 type: 'object',
277 title: 'Phone number changed',
278 purpose: 'Notify users when their phone number has changed',
279 properties: {
280 MAILER_SUBJECTS_PHONE_CHANGED_NOTIFICATION: { title: 'Subject', type: 'string' },
281 MAILER_TEMPLATES_PHONE_CHANGED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
282 },
283 variables: [
284 TemplateVariables.Email,
285 TemplateVariables.Phone,
286 TemplateVariables.OldPhone,
287 TemplateVariables.Data,
288 ],
289 validationSchema: z.object({
290 MAILER_SUBJECTS_PHONE_CHANGED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
291 }),
292 misc: {
293 emailTemplateType: 'security',
294 },
295}
296
297const IDENTITY_LINKED_NOTIFICATION: AuthTemplate = {
298 id: 'IDENTITY_LINKED_NOTIFICATION',
299 type: 'object',
300 title: 'Identity linked',
301 purpose: 'Notify users when a new identity has been linked to their account',
302 properties: {
303 MAILER_SUBJECTS_IDENTITY_LINKED_NOTIFICATION: { title: 'Subject', type: 'string' },
304 MAILER_TEMPLATES_IDENTITY_LINKED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
305 },
306 variables: [TemplateVariables.Email, TemplateVariables.Provider, TemplateVariables.Data],
307 validationSchema: z.object({
308 MAILER_SUBJECTS_IDENTITY_LINKED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
309 }),
310 misc: {
311 emailTemplateType: 'security',
312 },
313}
314
315const IDENTITY_UNLINKED_NOTIFICATION: AuthTemplate = {
316 id: 'IDENTITY_UNLINKED_NOTIFICATION',
317 type: 'object',
318 title: 'Identity unlinked',
319 purpose: 'Notify users when an identity has been unlinked from their account',
320 properties: {
321 MAILER_SUBJECTS_IDENTITY_UNLINKED_NOTIFICATION: { title: 'Subject', type: 'string' },
322 MAILER_TEMPLATES_IDENTITY_UNLINKED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
323 },
324 variables: [TemplateVariables.Email, TemplateVariables.Provider, TemplateVariables.Data],
325 validationSchema: z.object({
326 MAILER_SUBJECTS_IDENTITY_UNLINKED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
327 }),
328 misc: {
329 emailTemplateType: 'security',
330 },
331}
332
333const MFA_FACTOR_ENROLLED_NOTIFICATION: AuthTemplate = {
334 id: 'MFA_FACTOR_ENROLLED_NOTIFICATION',
335 type: 'object',
336 title: 'MFA method added',
337 purpose: 'Notify users when an MFA method has been added to their account',
338 properties: {
339 MAILER_SUBJECTS_MFA_FACTOR_ENROLLED_NOTIFICATION: { title: 'Subject', type: 'string' },
340 MAILER_TEMPLATES_MFA_FACTOR_ENROLLED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
341 },
342 variables: [TemplateVariables.Email, TemplateVariables.FactorType, TemplateVariables.Data],
343 validationSchema: z.object({
344 MAILER_SUBJECTS_MFA_FACTOR_ENROLLED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
345 }),
346 misc: {
347 emailTemplateType: 'security',
348 },
349}
350
351const MFA_FACTOR_UNENROLLED_NOTIFICATION: AuthTemplate = {
352 id: 'MFA_FACTOR_UNENROLLED_NOTIFICATION',
353 type: 'object',
354 title: 'MFA method removed',
355 purpose: 'Notify users when an MFA method has been removed from their account',
356 properties: {
357 MAILER_SUBJECTS_MFA_FACTOR_UNENROLLED_NOTIFICATION: { title: 'Subject', type: 'string' },
358 MAILER_TEMPLATES_MFA_FACTOR_UNENROLLED_NOTIFICATION_CONTENT: { title: 'Body', type: 'code' },
359 },
360 variables: [TemplateVariables.Email, TemplateVariables.FactorType, TemplateVariables.Data],
361 validationSchema: z.object({
362 MAILER_SUBJECTS_MFA_FACTOR_UNENROLLED_NOTIFICATION: z.string().min(1, 'Subject is required.'),
363 }),
364 misc: {
365 emailTemplateType: 'security',
366 },
367}
368
369export const TEMPLATES_SCHEMAS = [
370 CONFIRMATION,
371 INVITE,
372 MAGIC_LINK,
373 EMAIL_CHANGE,
374 RECOVERY,
375 REAUTHENTICATION,
376 // Notifications
377 PASSWORD_CHANGED_NOTIFICATION,
378 EMAIL_CHANGED_NOTIFICATION,
379 PHONE_CHANGED_NOTIFICATION,
380 IDENTITY_LINKED_NOTIFICATION,
381 IDENTITY_UNLINKED_NOTIFICATION,
382 MFA_FACTOR_ENROLLED_NOTIFICATION,
383 MFA_FACTOR_UNENROLLED_NOTIFICATION,
384]