@contember/react-client-tenant 2.2.0-alpha.5 → 2.2.0-alpha.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/dist/development/src/components/forms/LoginForm.cjs +2 -0
  2. package/dist/development/src/components/forms/LoginForm.cjs.map +1 -1
  3. package/dist/development/src/components/forms/LoginForm.js +2 -0
  4. package/dist/development/src/components/forms/LoginForm.js.map +1 -1
  5. package/dist/development/src/components/forms/PasswordlessSignInForm.cjs +2 -1
  6. package/dist/development/src/components/forms/PasswordlessSignInForm.cjs.map +1 -1
  7. package/dist/development/src/components/forms/PasswordlessSignInForm.js +2 -1
  8. package/dist/development/src/components/forms/PasswordlessSignInForm.js.map +1 -1
  9. package/dist/development/src/components/forms/PasswordlessSignInInitForm.cjs +2 -1
  10. package/dist/development/src/components/forms/PasswordlessSignInInitForm.cjs.map +1 -1
  11. package/dist/development/src/components/forms/PasswordlessSignInInitForm.js +2 -1
  12. package/dist/development/src/components/forms/PasswordlessSignInInitForm.js.map +1 -1
  13. package/dist/production/src/components/forms/LoginForm.cjs +2 -0
  14. package/dist/production/src/components/forms/LoginForm.cjs.map +1 -1
  15. package/dist/production/src/components/forms/LoginForm.js +2 -0
  16. package/dist/production/src/components/forms/LoginForm.js.map +1 -1
  17. package/dist/production/src/components/forms/PasswordlessSignInForm.cjs +2 -1
  18. package/dist/production/src/components/forms/PasswordlessSignInForm.cjs.map +1 -1
  19. package/dist/production/src/components/forms/PasswordlessSignInForm.js +2 -1
  20. package/dist/production/src/components/forms/PasswordlessSignInForm.js.map +1 -1
  21. package/dist/production/src/components/forms/PasswordlessSignInInitForm.cjs +2 -1
  22. package/dist/production/src/components/forms/PasswordlessSignInInitForm.cjs.map +1 -1
  23. package/dist/production/src/components/forms/PasswordlessSignInInitForm.js +2 -1
  24. package/dist/production/src/components/forms/PasswordlessSignInInitForm.js.map +1 -1
  25. package/dist/types/hooks/queries/useIdentityProvidersQuery.d.ts +2 -0
  26. package/dist/types/hooks/queries/useIdentityProvidersQuery.d.ts.map +1 -1
  27. package/dist/types/tsconfig.tsbuildinfo +1 -1
  28. package/package.json +5 -5
  29. package/src/components/forms/LoginForm.tsx +2 -0
  30. package/src/components/forms/PasswordlessSignInForm.tsx +1 -0
  31. package/src/components/forms/PasswordlessSignInInitForm.tsx +1 -0
@@ -84,6 +84,8 @@ const errorToField = {
84
84
  "RATE_LIMIT_EXCEEDED": "password",
85
85
  "OTP_REQUIRED": void 0,
86
86
  "MFA_ENROLLMENT_REQUIRED": void 0,
87
+ // Form-level, not a field: it is the account that cannot use a local credential.
88
+ "IDP_REQUIRED": void 0,
87
89
  "EMAIL_NOT_VERIFIED": "email"
88
90
  };
89
91
  exports.LoginForm = LoginForm;
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["useForm","useSignInMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsxDEV","TenantForm","this"],"mappings":";;;;;;;;AAsCO,MAAM,eAAeA,SAAAA;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQC,kBAAAA,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,IAlDF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AAqDF;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA,EAC3B,sBAAsB;AACvB;;;"}
1
+ {"version":3,"file":"LoginForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t// Form-level, not a field: it is the account that cannot use a local credential.\n\t'IDP_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["useForm","useSignInMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsxDEV","TenantForm","this"],"mappings":";;;;;;;;AAsCO,MAAM,eAAeA,SAAAA;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQC,kBAAAA,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,IAlDF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AAqDF;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA;AAAA,EAE3B,gBAAgB;AAAA,EAChB,sBAAsB;AACvB;;;"}
@@ -82,6 +82,8 @@ const errorToField = {
82
82
  "RATE_LIMIT_EXCEEDED": "password",
83
83
  "OTP_REQUIRED": void 0,
84
84
  "MFA_ENROLLMENT_REQUIRED": void 0,
85
+ // Form-level, not a field: it is the account that cannot use a local credential.
86
+ "IDP_REQUIRED": void 0,
85
87
  "EMAIL_NOT_VERIFIED": "email"
86
88
  };
87
89
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["this"],"mappings":";;;;;;AAsCO,MAAM,eAAe;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQ,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,IAlDF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AAqDF;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA,EAC3B,sBAAsB;AACvB;"}
1
+ {"version":3,"file":"LoginForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t// Form-level, not a field: it is the account that cannot use a local credential.\n\t'IDP_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["this"],"mappings":";;;;;;AAsCO,MAAM,eAAe;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQ,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,IAlDF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AAqDF;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA;AAAA,EAE3B,gBAAgB;AAAA,EAChB,sBAAsB;AACvB;"}
@@ -75,7 +75,8 @@ const errorToField = {
75
75
  TOKEN_INVALID: "token",
76
76
  INVALID_OTP_TOKEN: "otpToken",
77
77
  OTP_REQUIRED: void 0,
78
- MFA_ENROLLMENT_REQUIRED: void 0
78
+ MFA_ENROLLMENT_REQUIRED: void 0,
79
+ IDP_REQUIRED: void 0
79
80
  };
80
81
  exports.PasswordlessSignInForm = PasswordlessSignInForm;
81
82
  exports.usePasswordlessSignInForm = usePasswordlessSignInForm;
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n}\n"],"names":["useForm","useSignInPasswordlessMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsxDEV","TenantForm","useMemo","useCallback","this"],"mappings":";;;;;;;;;AA2CO,MAAM,4BAA4BA,SAAAA;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAASC,8BAAAA,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,IAxCF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AA2CF;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAC1B;;;"}
1
+ {"version":3,"file":"PasswordlessSignInForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["useForm","useSignInPasswordlessMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsxDEV","TenantForm","useMemo","useCallback","this"],"mappings":";;;;;;;;;AA2CO,MAAM,4BAA4BA,SAAAA;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAASC,8BAAAA,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,IAxCF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AA2CF;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAAA,EACzB,cAAc;AACf;;;"}
@@ -73,7 +73,8 @@ const errorToField = {
73
73
  TOKEN_INVALID: "token",
74
74
  INVALID_OTP_TOKEN: "otpToken",
75
75
  OTP_REQUIRED: void 0,
76
- MFA_ENROLLMENT_REQUIRED: void 0
76
+ MFA_ENROLLMENT_REQUIRED: void 0,
77
+ IDP_REQUIRED: void 0
77
78
  };
78
79
  export {
79
80
  PasswordlessSignInForm,
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n}\n"],"names":["this"],"mappings":";;;;;;;AA2CO,MAAM,4BAA4B;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAAS,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,IAxCF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AA2CF;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAC1B;"}
1
+ {"version":3,"file":"PasswordlessSignInForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["this"],"mappings":";;;;;;;AA2CO,MAAM,4BAA4B;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAAS,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,IAxCF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AA2CF;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAAA,EACzB,cAAc;AACf;"}
@@ -54,7 +54,8 @@ const errorToField = {
54
54
  PERSON_NOT_FOUND: "email",
55
55
  PASSWORDLESS_DISABLED: void 0,
56
56
  RATE_LIMIT_EXCEEDED: void 0,
57
- INVALID_CAPTCHA: void 0
57
+ INVALID_CAPTCHA: void 0,
58
+ IDP_REQUIRED: void 0
58
59
  };
59
60
  exports.PasswordlessSignInInitForm = PasswordlessSignInInitForm;
60
61
  exports.usePasswordlessSignInInitForm = usePasswordlessSignInInitForm;
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInInitForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n}\n"],"names":["useForm","useInitSignInPasswordlessMutation","useSaveBacklink","jsxDEV","TenantForm","PASSWORDLESS_REQUEST_STORAGE_KEY","useMemo","useCallback","this"],"mappings":";;;;;;;;;AA8BO,MAAM,gCAAgCA,SAAAA;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAaC,kCAAAA,kCAAA;AACnB,QAAM,eAAeC,sBAAAA,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQC,OAAAA,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,IAxBF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AA2BF;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAClB;;;"}
1
+ {"version":3,"file":"PasswordlessSignInInitForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["useForm","useInitSignInPasswordlessMutation","useSaveBacklink","jsxDEV","TenantForm","PASSWORDLESS_REQUEST_STORAGE_KEY","useMemo","useCallback","this"],"mappings":";;;;;;;;;AA8BO,MAAM,gCAAgCA,SAAAA;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAaC,kCAAAA,kCAAA;AACnB,QAAM,eAAeC,sBAAAA,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACCC,8BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQC,OAAAA,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,IAxBF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAC;AAAAA,EAAA;AA2BF;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,cAAc;AACf;;;"}
@@ -52,7 +52,8 @@ const errorToField = {
52
52
  PERSON_NOT_FOUND: "email",
53
53
  PASSWORDLESS_DISABLED: void 0,
54
54
  RATE_LIMIT_EXCEEDED: void 0,
55
- INVALID_CAPTCHA: void 0
55
+ INVALID_CAPTCHA: void 0,
56
+ IDP_REQUIRED: void 0
56
57
  };
57
58
  export {
58
59
  PasswordlessSignInInitForm,
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInInitForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n}\n"],"names":["this"],"mappings":";;;;;;;AA8BO,MAAM,gCAAgC;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAa,kCAAA;AACnB,QAAM,eAAe,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQ,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,IAxBF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AA2BF;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAClB;"}
1
+ {"version":3,"file":"PasswordlessSignInInitForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["this"],"mappings":";;;;;;;AA8BO,MAAM,gCAAgC;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAa,kCAAA;AACnB,QAAM,eAAe,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQ,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,IAxBF;AAAA,IAAA;AAAA,IAAA;AAAA,MAAA,UAAA;AAAA,MAAA,YAAA;AAAA,MAAA,cAAA;AAAA,IAAA;AAAA,IAAAA;AAAAA,EAAA;AA2BF;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,cAAc;AACf;"}
@@ -76,6 +76,8 @@ const errorToField = {
76
76
  "RATE_LIMIT_EXCEEDED": "password",
77
77
  "OTP_REQUIRED": void 0,
78
78
  "MFA_ENROLLMENT_REQUIRED": void 0,
79
+ // Form-level, not a field: it is the account that cannot use a local credential.
80
+ "IDP_REQUIRED": void 0,
79
81
  "EMAIL_NOT_VERIFIED": "email"
80
82
  };
81
83
  exports.LoginForm = LoginForm;
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["useForm","useSignInMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsx","TenantForm"],"mappings":";;;;;;;;AAsCO,MAAM,eAAeA,SAAAA;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQC,kBAAAA,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA,EAC3B,sBAAsB;AACvB;;;"}
1
+ {"version":3,"file":"LoginForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t// Form-level, not a field: it is the account that cannot use a local credential.\n\t'IDP_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":["useForm","useSignInMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsx","TenantForm"],"mappings":";;;;;;;;AAsCO,MAAM,eAAeA,SAAAA;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQC,kBAAAA,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA;AAAA,EAE3B,gBAAgB;AAAA,EAChB,sBAAsB;AACvB;;;"}
@@ -74,6 +74,8 @@ const errorToField = {
74
74
  "RATE_LIMIT_EXCEEDED": "password",
75
75
  "OTP_REQUIRED": void 0,
76
76
  "MFA_ENROLLMENT_REQUIRED": void 0,
77
+ // Form-level, not a field: it is the account that cannot use a local credential.
78
+ "IDP_REQUIRED": void 0,
77
79
  "EMAIL_NOT_VERIFIED": "email"
78
80
  };
79
81
  export {
@@ -1 +1 @@
1
- {"version":3,"file":"LoginForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":[],"mappings":";;;;;;AAsCO,MAAM,eAAe;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQ,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA,EAC3B,sBAAsB;AACvB;"}
1
+ {"version":3,"file":"LoginForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/LoginForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { SignInErrorCode } from '@contember/graphql-client-tenant'\nimport { FormContextValue, FormError, FormState } from '../../types/index.js'\nimport { useForm } from '../../contexts.js'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { SignInMutationResult, useSignInMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type LoginFormValues = {\n\temail: string\n\tpassword: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type LoginFormErrorCode =\n\t| SignInErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type LoginFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type LoginFormError = FormError<LoginFormValues, LoginFormErrorCode>\n\nexport type LoginFormContextValue = FormContextValue<LoginFormValues, LoginFormErrorCode, LoginFormState>\n\nexport interface LoginFormProps {\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const useLoginForm = useForm as () => LoginFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\n\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const LoginForm = ({ children, expiration = DEFAULT_LOGIN_EXPIRATION, onSuccess }: LoginFormProps) => {\n\tconst login = useSignInMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<LoginFormContextValue, SignInMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={{\n\t\t\t\temail: '',\n\t\t\t\tpassword: '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tconst errors: LoginFormError[] = []\n\t\t\t\tif (!values.email) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'email' })\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'email' })\n\t\t\t\t}\n\n\t\t\t\tif (!values.password) {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'password' })\n\t\t\t\t} else if (values.password.length < 6) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'password' })\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\terrors.push({ code: 'FIELD_REQUIRED', field: 'otpToken' })\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\terrors.push({ code: 'INVALID_VALUE', field: 'otpToken' })\n\t\t\t\t}\n\t\t\t\treturn errors\n\t\t\t}}\n\t\t\texecute={async ({ values }) => {\n\t\t\t\tconst result = await login({\n\t\t\t\t\temail: values.email!,\n\t\t\t\t\tpassword: values.password!,\n\t\t\t\t\totpToken: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\texpiration: expiration,\n\t\t\t\t})\n\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInErrorCode, keyof LoginFormValues | undefined> = {\n\t'INVALID_PASSWORD': 'password',\n\t'NO_PASSWORD_SET': 'password',\n\t'UNKNOWN_EMAIL': 'email',\n\t'PERSON_DISABLED': 'email',\n\t'INVALID_OTP_TOKEN': 'otpToken',\n\t'INVALID_CREDENTIALS': 'password',\n\t'RATE_LIMIT_EXCEEDED': 'password',\n\t'OTP_REQUIRED': undefined,\n\t'MFA_ENROLLMENT_REQUIRED': undefined,\n\t// Form-level, not a field: it is the account that cannot use a local credential.\n\t'IDP_REQUIRED': undefined,\n\t'EMAIL_NOT_VERIFIED': 'email',\n}\n"],"names":[],"mappings":";;;;;;AAsCO,MAAM,eAAe;AAE5B,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AAEA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,YAAY,CAAC,EAAE,UAAU,aAAa,0BAA0B,gBAAgC;AAC5G,QAAM,QAAQ,kBAAkB,EAAE,SAAS;AAC3C,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe;AAAA,QACd,OAAO;AAAA,QACP,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MAAA;AAAA,MAEb,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,cAAM,SAA2B,CAAA;AACjC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACvD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QACtD;AAEA,YAAI,CAAC,OAAO,UAAU;AACrB,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,SAAS,SAAS,GAAG;AACtC,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,KAAK,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QAC1D,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,KAAK,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACzD;AACA,eAAO;AAAA,MACR;AAAA,MACA,SAAS,OAAO,EAAE,aAAa;AAC9B,cAAM,SAAS,MAAM,MAAM;AAAA,UAC1B,OAAO,OAAO;AAAA,UACd,UAAU,OAAO;AAAA,UACjB,UAAU,OAAO,YAAY;AAAA,UAC7B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AAED,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR;AAAA,MAEC;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAqF;AAAA,EAC1F,oBAAoB;AAAA,EACpB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qBAAqB;AAAA,EACrB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,2BAA2B;AAAA;AAAA,EAE3B,gBAAgB;AAAA,EAChB,sBAAsB;AACvB;"}
@@ -67,7 +67,8 @@ const errorToField = {
67
67
  TOKEN_INVALID: "token",
68
68
  INVALID_OTP_TOKEN: "otpToken",
69
69
  OTP_REQUIRED: void 0,
70
- MFA_ENROLLMENT_REQUIRED: void 0
70
+ MFA_ENROLLMENT_REQUIRED: void 0,
71
+ IDP_REQUIRED: void 0
71
72
  };
72
73
  exports.PasswordlessSignInForm = PasswordlessSignInForm;
73
74
  exports.usePasswordlessSignInForm = usePasswordlessSignInForm;
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n}\n"],"names":["useForm","useSignInPasswordlessMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsx","TenantForm","useMemo","useCallback"],"mappings":";;;;;;;;;AA2CO,MAAM,4BAA4BA,SAAAA;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAASC,8BAAAA,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAC1B;;;"}
1
+ {"version":3,"file":"PasswordlessSignInForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["useForm","useSignInPasswordlessMutation","useRedirectToBacklinkCallback","useSetSessionToken","jsx","TenantForm","useMemo","useCallback"],"mappings":";;;;;;;;;AA2CO,MAAM,4BAA4BA,SAAAA;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAASC,8BAAAA,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqBC,sBAAAA,8BAAA;AAC3B,QAAM,kBAAkBC,YAAAA,mBAAA;AACxB,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAAA,EACzB,cAAc;AACf;;;"}
@@ -65,7 +65,8 @@ const errorToField = {
65
65
  TOKEN_INVALID: "token",
66
66
  INVALID_OTP_TOKEN: "otpToken",
67
67
  OTP_REQUIRED: void 0,
68
- MFA_ENROLLMENT_REQUIRED: void 0
68
+ MFA_ENROLLMENT_REQUIRED: void 0,
69
+ IDP_REQUIRED: void 0
69
70
  };
70
71
  export {
71
72
  PasswordlessSignInForm,
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n}\n"],"names":[],"mappings":";;;;;;;AA2CO,MAAM,4BAA4B;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAAS,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAC1B;"}
1
+ {"version":3,"file":"PasswordlessSignInForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInForm.tsx"],"sourcesContent":["import * as TenantApi from '@contember/graphql-client-tenant'\nimport { useSetSessionToken } from '@contember/react-client'\nimport { ReactElement, useCallback, useMemo } from 'react'\nimport { useForm } from '../../contexts.js'\nimport { SignInPasswordlessMutationResult, useSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { useRedirectToBacklinkCallback } from '../../internal/hooks/useRedirectToBacklink.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { TenantForm } from './TenantForm.js'\n\nexport type PasswordlessSignInFormValues = {\n\ttoken: string\n\totpToken: string\n\t/** Alternative to `otpToken` for a user who lost their authenticator. */\n\tbackupCode: string\n}\n\nexport type PasswordlessSignInFormErrorCode =\n\t| TenantApi.SignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInFormState =\n\t| FormState\n\t| 'otp-required'\n\nexport type PasswordlessSignInFormError = FormError<PasswordlessSignInFormValues, PasswordlessSignInFormErrorCode>\n\nexport type PasswordlessSignInFormContextValue = FormContextValue<\n\tPasswordlessSignInFormValues,\n\tPasswordlessSignInFormErrorCode,\n\tPasswordlessSignInFormState\n>\n\nexport interface PasswordlessSignInFormProps {\n\trequestId: string\n\tvalidationType: TenantApi.PasswordlessValidationType\n\ttoken?: string\n\texpiration?: number\n\tchildren: ReactElement\n\tonSuccess?: () => void\n}\n\nexport const usePasswordlessSignInForm = useForm as () => PasswordlessSignInFormContextValue\n\nconst headers = {\n\t'X-Contember-Token-Path': 'data.mutation.result.token',\n}\nconst DEFAULT_LOGIN_EXPIRATION = 14 * 24 * 60 // 14 days\n\nexport const PasswordlessSignInForm = (\n\t{ children, onSuccess, requestId, validationType, token, expiration = DEFAULT_LOGIN_EXPIRATION }: PasswordlessSignInFormProps,\n) => {\n\tconst signIn = useSignInPasswordlessMutation({ headers })\n\tconst redirectToBacklink = useRedirectToBacklinkCallback()\n\tconst setSessionToken = useSetSessionToken()\n\treturn (\n\t\t<TenantForm<PasswordlessSignInFormContextValue, SignInPasswordlessMutationResult>\n\t\t\tonSuccess={args => {\n\t\t\t\tonSuccess?.()\n\t\t\t\tsetSessionToken(args.result.token)\n\t\t\t\tredirectToBacklink()\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\ttoken: token ?? '',\n\t\t\t\totpToken: '',\n\t\t\t\tbackupCode: '',\n\t\t\t}), [token])}\n\t\t\tvalidate={({ values, state }) => {\n\t\t\t\tif (!values.token) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'token' }]\n\t\t\t\t}\n\t\t\t\t// In the otp-required step either an otpToken or a backup code will do.\n\t\t\t\tif (!values.otpToken && !values.backupCode && state === 'otp-required') {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'otpToken' }]\n\t\t\t\t} else if (values.otpToken && !values.otpToken.match(/^\\d{6}$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'otpToken' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\tconst result = await signIn({\n\t\t\t\t\trequestId,\n\t\t\t\t\texpiration,\n\t\t\t\t\ttoken: values.token,\n\t\t\t\t\tmfaOtp: values.otpToken || undefined,\n\t\t\t\t\tbackupCode: values.backupCode || undefined,\n\t\t\t\t\tvalidationType,\n\t\t\t\t})\n\t\t\t\tif (!result.ok && result.error === 'OTP_REQUIRED') {\n\t\t\t\t\treturn { ...result, state: 'otp-required' }\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}, [expiration, requestId, signIn, validationType])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.SignInPasswordlessErrorCode, keyof PasswordlessSignInFormValues | undefined> = {\n\tPERSON_DISABLED: undefined,\n\tTOKEN_EXPIRED: 'token',\n\tTOKEN_NOT_FOUND: 'token',\n\tTOKEN_USED: 'token',\n\tTOKEN_INVALID: 'token',\n\tINVALID_OTP_TOKEN: 'otpToken',\n\tOTP_REQUIRED: undefined,\n\tMFA_ENROLLMENT_REQUIRED: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":[],"mappings":";;;;;;;AA2CO,MAAM,4BAA4B;AAEzC,MAAM,UAAU;AAAA,EACf,0BAA0B;AAC3B;AACA,MAAM,2BAA2B,KAAK,KAAK;AAEpC,MAAM,yBAAyB,CACrC,EAAE,UAAU,WAAW,WAAW,gBAAgB,OAAO,aAAa,+BAClE;AACJ,QAAM,SAAS,8BAA8B,EAAE,SAAS;AACxD,QAAM,qBAAqB,8BAAA;AAC3B,QAAM,kBAAkB,mBAAA;AACxB,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,SAAQ;AAClB,oBAAA;AACA,wBAAgB,KAAK,OAAO,KAAK;AACjC,2BAAA;AAAA,MACD;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO,SAAS;AAAA,QAChB,UAAU;AAAA,QACV,YAAY;AAAA,MAAA,IACT,CAAC,KAAK,CAAC;AAAA,MACX,UAAU,CAAC,EAAE,QAAQ,YAAY;AAChC,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD;AAEA,YAAI,CAAC,OAAO,YAAY,CAAC,OAAO,cAAc,UAAU,gBAAgB;AACvE,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,YAAY;AAAA,QACtD,WAAW,OAAO,YAAY,CAAC,OAAO,SAAS,MAAM,SAAS,GAAG;AAChE,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,YAAY;AAAA,QACrD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,cAAM,SAAS,MAAM,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,OAAO,OAAO;AAAA,UACd,QAAQ,OAAO,YAAY;AAAA,UAC3B,YAAY,OAAO,cAAc;AAAA,UACjC;AAAA,QAAA,CACA;AACD,YAAI,CAAC,OAAO,MAAM,OAAO,UAAU,gBAAgB;AAClD,iBAAO,EAAE,GAAG,QAAQ,OAAO,eAAA;AAAA,QAC5B;AAEA,eAAO;AAAA,MACR,GAAG,CAAC,YAAY,WAAW,QAAQ,cAAc,CAAC;AAAA,MAEjD;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAA8G;AAAA,EACnH,iBAAiB;AAAA,EACjB,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,mBAAmB;AAAA,EACnB,cAAc;AAAA,EACd,yBAAyB;AAAA,EACzB,cAAc;AACf;"}
@@ -46,7 +46,8 @@ const errorToField = {
46
46
  PERSON_NOT_FOUND: "email",
47
47
  PASSWORDLESS_DISABLED: void 0,
48
48
  RATE_LIMIT_EXCEEDED: void 0,
49
- INVALID_CAPTCHA: void 0
49
+ INVALID_CAPTCHA: void 0,
50
+ IDP_REQUIRED: void 0
50
51
  };
51
52
  exports.PasswordlessSignInInitForm = PasswordlessSignInInitForm;
52
53
  exports.usePasswordlessSignInInitForm = usePasswordlessSignInInitForm;
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInInitForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n}\n"],"names":["useForm","useInitSignInPasswordlessMutation","useSaveBacklink","jsx","TenantForm","PASSWORDLESS_REQUEST_STORAGE_KEY","useMemo","useCallback"],"mappings":";;;;;;;;;AA8BO,MAAM,gCAAgCA,SAAAA;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAaC,kCAAAA,kCAAA;AACnB,QAAM,eAAeC,sBAAAA,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQC,OAAAA,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAClB;;;"}
1
+ {"version":3,"file":"PasswordlessSignInInitForm.cjs","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":["useForm","useInitSignInPasswordlessMutation","useSaveBacklink","jsx","TenantForm","PASSWORDLESS_REQUEST_STORAGE_KEY","useMemo","useCallback"],"mappings":";;;;;;;;;AA8BO,MAAM,gCAAgCA,SAAAA;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAaC,kCAAAA,kCAAA;AACnB,QAAM,eAAeC,sBAAAA,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACCC,2BAAAA;AAAAA,IAACC,WAAAA;AAAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQC,OAAAA,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAeC,MAAAA,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAASC,MAAAA,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,cAAc;AACf;;;"}
@@ -44,7 +44,8 @@ const errorToField = {
44
44
  PERSON_NOT_FOUND: "email",
45
45
  PASSWORDLESS_DISABLED: void 0,
46
46
  RATE_LIMIT_EXCEEDED: void 0,
47
- INVALID_CAPTCHA: void 0
47
+ INVALID_CAPTCHA: void 0,
48
+ IDP_REQUIRED: void 0
48
49
  };
49
50
  export {
50
51
  PasswordlessSignInInitForm,
@@ -1 +1 @@
1
- {"version":3,"file":"PasswordlessSignInInitForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n}\n"],"names":[],"mappings":";;;;;;;AA8BO,MAAM,gCAAgC;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAa,kCAAA;AACnB,QAAM,eAAe,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQ,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAClB;"}
1
+ {"version":3,"file":"PasswordlessSignInInitForm.js","sources":["../../../../../../packages/react-client-tenant/src/components/forms/PasswordlessSignInInitForm.tsx"],"sourcesContent":["import { ReactElement, useCallback, useMemo } from 'react'\nimport * as TenantApi from '@contember/graphql-client-tenant'\nimport { TenantForm } from './TenantForm.js'\nimport { FormContextValue, FormError, FormState } from '../../types/forms.js'\nimport { useForm } from '../../contexts.js'\nimport { InitSignInPasswordlessMutationResult, useInitSignInPasswordlessMutation } from '../../hooks/index.js'\nimport { PASSWORDLESS_REQUEST_STORAGE_KEY } from '../../consts.js'\nimport { useSaveBacklink } from '../../internal/hooks/useRedirectToBacklink.js'\n\nexport type PasswordlessSignInInitFormValues = {\n\temail: string\n}\n\nexport type PasswordlessSignInInitFormErrorCode =\n\t| TenantApi.InitSignInPasswordlessErrorCode\n\t| 'FIELD_REQUIRED'\n\t| 'INVALID_VALUE'\n\t| 'UNKNOWN_ERROR'\n\nexport type PasswordlessSignInInitFormState = FormState\n\nexport type PasswordlessSignInInitFormError = FormError<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport type PasswordlessSignInInitFormContextValue = FormContextValue<PasswordlessSignInInitFormValues, PasswordlessSignInInitFormErrorCode>\n\nexport interface PasswordlessSignInInitFormProps {\n\tchildren: ReactElement\n\tonSuccess?: (args: { result: InitSignInPasswordlessMutationResult }) => void\n}\n\nexport const usePasswordlessSignInInitForm = useForm as () => PasswordlessSignInInitFormContextValue\n\nexport const PasswordlessSignInInitForm = ({ children, onSuccess }: PasswordlessSignInInitFormProps) => {\n\tconst initSignIn = useInitSignInPasswordlessMutation()\n\tconst saveBacklink = useSaveBacklink({\n\t\tstorage: 'local',\n\t})\n\n\treturn (\n\t\t<TenantForm<PasswordlessSignInInitFormContextValue, InitSignInPasswordlessMutationResult>\n\t\t\tonSuccess={res => {\n\t\t\t\tlocalStorage.setItem(PASSWORDLESS_REQUEST_STORAGE_KEY, res.result.requestId)\n\t\t\t\tsaveBacklink()\n\t\t\t\tonSuccess?.(res)\n\t\t\t}}\n\t\t\terrorMapping={errorToField}\n\t\t\tinitialValues={useMemo(() => ({\n\t\t\t\temail: '',\n\t\t\t}), [])}\n\t\t\tvalidate={({ values }) => {\n\t\t\t\tif (!values.email) {\n\t\t\t\t\treturn [{ code: 'FIELD_REQUIRED', field: 'email' }]\n\t\t\t\t} else if (!values.email.match(/^.+@.+$/)) {\n\t\t\t\t\treturn [{ code: 'INVALID_VALUE', field: 'email' }]\n\t\t\t\t}\n\t\t\t\treturn []\n\t\t\t}}\n\t\t\texecute={useCallback(async ({ values }) => {\n\t\t\t\treturn await initSignIn({\n\t\t\t\t\temail: values.email,\n\t\t\t\t})\n\t\t\t}, [initSignIn])}\n\t\t>\n\t\t\t{children}\n\t\t</TenantForm>\n\t)\n}\nconst errorToField: Record<TenantApi.InitSignInPasswordlessErrorCode, keyof PasswordlessSignInInitFormValues | undefined> = {\n\tPERSON_NOT_FOUND: 'email',\n\tPASSWORDLESS_DISABLED: undefined,\n\tRATE_LIMIT_EXCEEDED: undefined,\n\tINVALID_CAPTCHA: undefined,\n\tIDP_REQUIRED: undefined,\n}\n"],"names":[],"mappings":";;;;;;;AA8BO,MAAM,gCAAgC;AAEtC,MAAM,6BAA6B,CAAC,EAAE,UAAU,gBAAiD;AACvG,QAAM,aAAa,kCAAA;AACnB,QAAM,eAAe,gBAAgB;AAAA,IACpC,SAAS;AAAA,EAAA,CACT;AAED,SACC;AAAA,IAAC;AAAA,IAAA;AAAA,MACA,WAAW,CAAA,QAAO;AACjB,qBAAa,QAAQ,kCAAkC,IAAI,OAAO,SAAS;AAC3E,qBAAA;AACA,oBAAY,GAAG;AAAA,MAChB;AAAA,MACA,cAAc;AAAA,MACd,eAAe,QAAQ,OAAO;AAAA,QAC7B,OAAO;AAAA,MAAA,IACJ,CAAA,CAAE;AAAA,MACN,UAAU,CAAC,EAAE,aAAa;AACzB,YAAI,CAAC,OAAO,OAAO;AAClB,iBAAO,CAAC,EAAE,MAAM,kBAAkB,OAAO,SAAS;AAAA,QACnD,WAAW,CAAC,OAAO,MAAM,MAAM,SAAS,GAAG;AAC1C,iBAAO,CAAC,EAAE,MAAM,iBAAiB,OAAO,SAAS;AAAA,QAClD;AACA,eAAO,CAAA;AAAA,MACR;AAAA,MACA,SAAS,YAAY,OAAO,EAAE,aAAa;AAC1C,eAAO,MAAM,WAAW;AAAA,UACvB,OAAO,OAAO;AAAA,QAAA,CACd;AAAA,MACF,GAAG,CAAC,UAAU,CAAC;AAAA,MAEd;AAAA,IAAA;AAAA,EAAA;AAGJ;AACA,MAAM,eAAsH;AAAA,EAC3H,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,iBAAiB;AAAA,EACjB,cAAc;AACf;"}
@@ -20,6 +20,8 @@ declare const identityProviderFragment: TenantApi.IdentityProviderFetcher<{
20
20
  readonly requireVerifiedEmail: boolean;
21
21
  } & {
22
22
  readonly assumeEmailVerified: boolean;
23
+ } & {
24
+ readonly disableLocalAuthentication: boolean;
23
25
  };
24
26
  }, {}>;
25
27
  export type IdentityProvidersQueryResult = readonly ModelType<typeof identityProviderFragment>[];
@@ -1 +1 @@
1
- {"version":3,"file":"useIdentityProvidersQuery.d.ts","sourceRoot":"","sources":["../../../../src/hooks/queries/useIdentityProvidersQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAgB,MAAM,oBAAoB,CAAA;AAGnE,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;MACS,CAAA;AAEvC,MAAM,MAAM,4BAA4B,GAAG,SAAS,SAAS,CAAC,OAAO,wBAAwB,CAAC,EAAE,CAAA;AAEhG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,aAAa,gBAAgB,WAEpC,EAAE,KAAQ,OAAO,CAAC,4BAA4B,CAK5E,CAAA"}
1
+ {"version":3,"file":"useIdentityProvidersQuery.d.ts","sourceRoot":"","sources":["../../../../src/hooks/queries/useIdentityProvidersQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,SAAS,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AACjD,OAAO,EAAE,gBAAgB,EAAgB,MAAM,oBAAoB,CAAA;AAGnE,QAAA,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;MACS,CAAA;AAEvC,MAAM,MAAM,4BAA4B,GAAG,SAAS,SAAS,CAAC,OAAO,wBAAwB,CAAC,EAAE,CAAA;AAEhG;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,aAAa,gBAAgB,WAEpC,EAAE,KAAQ,OAAO,CAAC,4BAA4B,CAK5E,CAAA"}