diff --git a/package-lock.json b/package-lock.json index 688e090..a10944b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@authorizerdev/authorizer-react", - "version": "1.1.17", + "version": "1.1.19", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@authorizerdev/authorizer-react", - "version": "1.1.17", + "version": "1.1.19", "license": "MIT", "dependencies": { - "@authorizerdev/authorizer-js": "^1.2.18", + "@authorizerdev/authorizer-js": "^2.0.0-beta.1", "validator": "^13.11.0" }, "devDependencies": { @@ -64,9 +64,9 @@ } }, "node_modules/@authorizerdev/authorizer-js": { - "version": "1.2.18", - "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-1.2.18.tgz", - "integrity": "sha512-9j5U/4lqaaEcG78Zli+TtLJ0migSKhFwnXXunulAGTZOzQSTCJ/CSSPip5wWNa/Mkr6gdEMwk1HYfhIdk2A9Mg==", + "version": "2.0.0-beta.1", + "resolved": "https://registry.npmjs.org/@authorizerdev/authorizer-js/-/authorizer-js-2.0.0-beta.1.tgz", + "integrity": "sha512-HP90TUWqqV6DLA8+nDpKzSH86lFUW+Ie9z6gqs25AJchKSIYHdbPlFtcK0JGWBAGNM9SewG/ivj3d7JH84kzYw==", "dependencies": { "cross-fetch": "^3.1.5" }, diff --git a/package.json b/package.json index 0003d05..2cf1f48 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "version": "1.1.19", + "version": "1.2.0-beta.0", "license": "MIT", "main": "dist/index.js", "typings": "dist/index.d.ts", @@ -66,7 +66,7 @@ "typescript": "^5.2.2" }, "dependencies": { - "@authorizerdev/authorizer-js": "^1.2.18", + "@authorizerdev/authorizer-js": "^2.0.0-beta.1", "validator": "^13.11.0" } } diff --git a/src/components/AuthorizerBasicAuthLogin.tsx b/src/components/AuthorizerBasicAuthLogin.tsx index ef639eb..baae9fb 100644 --- a/src/components/AuthorizerBasicAuthLogin.tsx +++ b/src/components/AuthorizerBasicAuthLogin.tsx @@ -93,7 +93,12 @@ export const AuthorizerBasicAuthLogin: FC<{ data.roles = roles; } - const res = await authorizerRef.login(data); + const { data: res, errors } = await authorizerRef.login(data); + if (errors && errors.length) { + setError(errors[0].message); + setLoading(false); + return; + } // if totp is enabled for the first time show totp screen with scanner if ( res && diff --git a/src/components/AuthorizerForgotPassword.tsx b/src/components/AuthorizerForgotPassword.tsx index 4cfeccc..1d8bcf5 100644 --- a/src/components/AuthorizerForgotPassword.tsx +++ b/src/components/AuthorizerForgotPassword.tsx @@ -1,5 +1,6 @@ import React, { FC, useEffect, useState } from 'react'; import isEmail from 'validator/es/lib/isEmail'; +import isMobilePhone from 'validator/es/lib/isMobilePhone'; import styles from '../styles/default.css'; import { ButtonAppearance, MessageType, Views } from '../constants'; @@ -7,11 +8,19 @@ import { useAuthorizer } from '../contexts/AuthorizerContext'; import { StyledButton, StyledFooter, StyledLink } from '../styledComponents'; import { formatErrorMessage } from '../utils/format'; import { Message } from './Message'; +import { AuthorizerVerifyOtp } from './AuthorizerVerifyOtp'; +import { OtpDataType } from '../types'; interface InputDataType { - email: string | null; + email_or_phone_number: string | null; } +const initOtpData: OtpDataType = { + is_screen_visible: false, + email: '', + phone_number: '', +}; + export const AuthorizerForgotPassword: FC<{ setView?: (v: Views) => void; onForgotPassword?: (data: any) => void; @@ -20,11 +29,12 @@ export const AuthorizerForgotPassword: FC<{ const [error, setError] = useState(``); const [loading, setLoading] = useState(false); const [successMessage, setSuccessMessage] = useState(``); + const [otpData, setOtpData] = useState({ ...initOtpData }); const [formData, setFormData] = useState({ - email: null, + email_or_phone_number: null, }); const [errorData, setErrorData] = useState({ - email: null, + email_or_phone_number: null, }); const { authorizerRef, config } = useAuthorizer(); @@ -36,9 +46,26 @@ export const AuthorizerForgotPassword: FC<{ e.preventDefault(); try { setLoading(true); - - const res = await authorizerRef.forgotPassword({ - email: formData.email || '', + let email: string = ''; + let phone_number: string = ''; + if (formData.email_or_phone_number) { + if (isEmail(formData.email_or_phone_number)) { + email = formData.email_or_phone_number; + } else if (isMobilePhone(formData.email_or_phone_number)) { + phone_number = formData.email_or_phone_number; + } + } + if (!email && !phone_number) { + setErrorData({ + ...errorData, + email_or_phone_number: 'Invalid email or phone number', + }); + setLoading(false); + return; + } + const { data: res, errors } = await authorizerRef.forgotPassword({ + email: email, + phone_number: phone_number, state: urlProps?.state || '', redirect_uri: urlProps?.redirect_uri || @@ -46,12 +73,23 @@ export const AuthorizerForgotPassword: FC<{ window.location.origin, }); setLoading(false); - - if (res && res.message) { + if (errors && errors.length) { + setError(formatErrorMessage(errors[0]?.message)); + return; + } + if (res?.message) { setError(``); setSuccessMessage(res.message); + if (res?.should_show_mobile_otp_screen) { + setOtpData({ + ...otpData, + is_screen_visible: true, + email: email, + phone_number: phone_number, + }); + return; + } } - if (onForgotPassword) { onForgotPassword(res); } @@ -66,19 +104,43 @@ export const AuthorizerForgotPassword: FC<{ }; useEffect(() => { - if (formData.email === '') { - setErrorData({ ...errorData, email: 'Email is required' }); - } else if (formData.email && !isEmail(formData.email)) { - setErrorData({ ...errorData, email: 'Please enter valid email' }); + if (formData.email_or_phone_number === '') { + setErrorData({ + ...errorData, + email_or_phone_number: 'Email OR Phone Number is required', + }); + } else if ( + !isEmail(formData.email_or_phone_number || '') && + !isMobilePhone(formData.email_or_phone_number || '') + ) { + setErrorData({ + ...errorData, + email_or_phone_number: 'Invalid Email OR Phone Number', + }); } else { - setErrorData({ ...errorData, email: null }); + setErrorData({ ...errorData, email_or_phone_number: null }); } - }, [formData.email]); + }, [formData.email_or_phone_number]); if (successMessage) { return ; } + if (otpData.is_screen_visible) { + return ( + { + if (onForgotPassword) { + onForgotPassword({}); + } + }} + /> + ); + } + return ( <> {error && ( @@ -93,29 +155,39 @@ export const AuthorizerForgotPassword: FC<{
onInputChange('email', e.target.value)} + type="text" + value={formData.email_or_phone_number || ''} + onChange={(e) => + onInputChange('email_or_phone_number', e.target.value) + } /> - {errorData.email && ( -
{errorData.email}
+ {errorData.email_or_phone_number && ( +
+ {errorData.email_or_phone_number} +
)}

{loading ? `Processing ...` : `Send Email`} diff --git a/src/components/AuthorizerMagicLinkLogin.tsx b/src/components/AuthorizerMagicLinkLogin.tsx index 6494539..ea674c7 100644 --- a/src/components/AuthorizerMagicLinkLogin.tsx +++ b/src/components/AuthorizerMagicLinkLogin.tsx @@ -47,8 +47,12 @@ export const AuthorizerMagicLinkLogin: FC<{ if (roles && roles.length) { data.roles = roles; } - const res = await authorizerRef.magicLinkLogin(data); + const { data: res, errors } = await authorizerRef.magicLinkLogin(data); setLoading(false); + if (errors && errors.length) { + setError(formatErrorMessage(errors[0]?.message)); + return; + } if (res) { setError(``); diff --git a/src/components/AuthorizerResetPassword.tsx b/src/components/AuthorizerResetPassword.tsx index a958a4a..12deb46 100644 --- a/src/components/AuthorizerResetPassword.tsx +++ b/src/components/AuthorizerResetPassword.tsx @@ -41,12 +41,16 @@ export const AuthorizerResetPassword: FC = ({ onReset }) => { e.preventDefault(); setLoading(true); try { - const res = await authorizerRef.resetPassword({ + const { data: res, errors } = await authorizerRef.resetPassword({ token, password: formData.password || '', confirm_password: formData.confirmPassword || '', }); setLoading(false); + if (errors && errors.length) { + setError(formatErrorMessage(errors[0]?.message)); + return; + } setError(``); if (onReset) { onReset(res); diff --git a/src/components/AuthorizerSignup.tsx b/src/components/AuthorizerSignup.tsx index acaa53a..89968ba 100644 --- a/src/components/AuthorizerSignup.tsx +++ b/src/components/AuthorizerSignup.tsx @@ -85,7 +85,12 @@ export const AuthorizerSignup: FC<{ if (roles && roles.length) { data.roles = roles; } - const res = await authorizerRef.signup(data); + const { data: res, errors } = await authorizerRef.signup(data); + if (errors && errors.length) { + setError(formatErrorMessage(errors[0]?.message)); + setLoading(false); + return; + } if (res) { setError(``); diff --git a/src/components/AuthorizerVerifyOtp.tsx b/src/components/AuthorizerVerifyOtp.tsx index 522f64e..8b2a776 100644 --- a/src/components/AuthorizerVerifyOtp.tsx +++ b/src/components/AuthorizerVerifyOtp.tsx @@ -53,9 +53,12 @@ export const AuthorizerVerifyOtp: FC<{ data.state = urlProps.state; } data.is_totp = !!is_totp; - const res = await authorizerRef.verifyOtp(data); + const { data: res, errors } = await authorizerRef.verifyOtp(data); setLoading(false); - + if (errors && errors.length) { + setError(errors[0]?.message || ``); + return; + } if (res) { setError(``); setAuthData({ @@ -93,10 +96,14 @@ export const AuthorizerVerifyOtp: FC<{ try { setSendingOtp(true); - const res = await authorizerRef.resendOtp({ + const { data: res, errors } = await authorizerRef.resendOtp({ email, }); setSendingOtp(false); + if (errors && errors.length) { + setError(errors[0]?.message || ``); + return; + } if (res && res?.message) { setError(``); diff --git a/src/contexts/AuthorizerContext.tsx b/src/contexts/AuthorizerContext.tsx index 562edf7..7ca3a5a 100644 --- a/src/contexts/AuthorizerContext.tsx +++ b/src/contexts/AuthorizerContext.tsx @@ -142,11 +142,17 @@ export const AuthorizerProvider: FC<{ ); const getToken = async () => { - const metaRes = await authorizerRef.current.getMetaData(); - + const { data: metaRes, errors: metaResErrors } = + await authorizerRef.current.getMetaData(); try { - const res = await authorizerRef.current.getSession(); - if (res.access_token && res.user) { + if (metaResErrors && metaResErrors.length) { + throw new Error(metaResErrors[0].message); + } + const { data: res, errors } = await authorizerRef.current.getSession(); + if (errors && errors.length) { + throw new Error(errors[0].message); + } + if (res && res.access_token && res.user) { const token = { access_token: res.access_token, expires_in: res.expires_in,