AuthTemplatesValidation.tsx 12 KB

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