Skip to content

Commit

Permalink
Merge pull request #45 from authorizerdev/feat/update-js-major
Browse files Browse the repository at this point in the history
feat: update js major version
  • Loading branch information
lakhansamani authored Dec 26, 2023
2 parents 5cf167c + 5e6a16f commit bd6ee6c
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 52 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.1.18",
"version": "1.2.0",
"license": "MIT",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down Expand Up @@ -66,7 +66,7 @@
"typescript": "^5.2.2"
},
"dependencies": {
"@authorizerdev/authorizer-js": "^1.2.18",
"@authorizerdev/authorizer-js": "^2.0.0-beta.3",
"validator": "^13.11.0"
}
}
7 changes: 6 additions & 1 deletion src/components/AuthorizerBasicAuthLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down
130 changes: 100 additions & 30 deletions src/components/AuthorizerForgotPassword.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
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';
import { useAuthorizer } from '../contexts/AuthorizerContext';
import { StyledButton, StyledFooter, StyledLink } from '../styledComponents';
import { formatErrorMessage } from '../utils/format';
import { Message } from './Message';
import { OtpDataType } from '../types';
import { AuthorizerResetPassword } from './AuthorizerResetPassword';

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;
onPasswordReset?: () => void;
urlProps?: Record<string, any>;
}> = ({ setView, onForgotPassword, urlProps }) => {
}> = ({ setView, onForgotPassword, onPasswordReset, urlProps }) => {
const [error, setError] = useState(``);
const [loading, setLoading] = useState(false);
const [successMessage, setSuccessMessage] = useState(``);
const [otpData, setOtpData] = useState<OtpDataType>({ ...initOtpData });
const [formData, setFormData] = useState<InputDataType>({
email: null,
email_or_phone_number: null,
});
const [errorData, setErrorData] = useState<InputDataType>({
email: null,
email_or_phone_number: null,
});
const { authorizerRef, config } = useAuthorizer();

Expand All @@ -36,22 +47,50 @@ 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 ||
config.redirectURL ||
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);
}
Expand All @@ -66,17 +105,38 @@ 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 (
formData.email_or_phone_number !== null &&
!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 <Message type={MessageType.Success} text={successMessage} />;
return (
<>
<Message type={MessageType.Success} text={successMessage} />
{otpData.is_screen_visible && (
<AuthorizerResetPassword
showOTPInput
onReset={onPasswordReset}
phone_number={otpData.phone_number}
/>
)}
</>
);
}

return (
Expand All @@ -93,32 +153,42 @@ export const AuthorizerForgotPassword: FC<{
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-forgot-password-email"
htmlFor="authorizer-forgot-password-email-or-phone-number"
>
<span>* </span>Email
<span>* </span>Email / Phone Number
</label>
<input
name="email"
id="authorizer-forgot-password-email"
name="email_or_phone_number"
id="authorizer-forgot-password-email-or-phone-number"
className={`${styles['form-input-field']} ${
errorData.email ? styles['input-error-content'] : null
errorData.email_or_phone_number
? styles['input-error-content']
: null
}`}
placeholder="eg. [email protected]"
type="email"
value={formData.email || ''}
onChange={(e) => onInputChange('email', e.target.value)}
placeholder="eg. [email protected] / +919999999999"
type="text"
value={formData.email_or_phone_number || ''}
onChange={(e) =>
onInputChange('email_or_phone_number', e.target.value)
}
/>
{errorData.email && (
<div className={styles['form-input-error']}>{errorData.email}</div>
{errorData.email_or_phone_number && (
<div className={styles['form-input-error']}>
{errorData.email_or_phone_number}
</div>
)}
</div>
<br />
<StyledButton
type="submit"
disabled={loading || !!errorData.email || !formData.email}
disabled={
loading ||
!!errorData.email_or_phone_number ||
!formData.email_or_phone_number
}
appearance={ButtonAppearance.Primary}
>
{loading ? `Processing ...` : `Send Email`}
{loading ? `Processing ...` : `Request Change`}
</StyledButton>
</form>
{setView && (
Expand Down
6 changes: 5 additions & 1 deletion src/components/AuthorizerMagicLinkLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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(``);
Expand Down
45 changes: 42 additions & 3 deletions src/components/AuthorizerResetPassword.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,32 @@ import { getSearchParams } from '../utils/url';
import PasswordStrengthIndicator from './PasswordStrengthIndicator';

type Props = {
showOTPInput?: boolean;
onReset?: (res: any) => void;
phone_number?: string;
};

interface InputDataType {
otp: string | null;
password: string | null;
confirmPassword: string | null;
}

export const AuthorizerResetPassword: FC<Props> = ({ onReset }) => {
export const AuthorizerResetPassword: FC<Props> = ({
onReset,
showOTPInput,
phone_number,
}) => {
const { token, redirect_uri } = getSearchParams();
const [error, setError] = useState(!token ? `Invalid token` : ``);
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [formData, setFormData] = useState<InputDataType>({
otp: null,
password: null,
confirmPassword: null,
});
const [errorData, setErrorData] = useState<InputDataType>({
otp: null,
password: null,
confirmPassword: null,
});
Expand All @@ -41,12 +50,18 @@ export const AuthorizerResetPassword: FC<Props> = ({ onReset }) => {
e.preventDefault();
setLoading(true);
try {
const res = await authorizerRef.resetPassword({
const { data: res, errors } = await authorizerRef.resetPassword({
token,
otp: formData.otp || '',
phone_number: phone_number || '',
password: formData.password || '',
confirm_password: formData.confirmPassword || '',
});
setLoading(false);
if (errors && errors.length) {
setError(formatErrorMessage(errors[0]?.message));
return;
}
setError(``);
if (onReset) {
onReset(res);
Expand Down Expand Up @@ -107,6 +122,30 @@ export const AuthorizerResetPassword: FC<Props> = ({ onReset }) => {
<Message type={MessageType.Error} text={error} onClose={onErrorClose} />
)}
<form onSubmit={onSubmit} name="authorizer-reset-password-form">
{showOTPInput && (
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
htmlFor="authorizer-verify-otp"
>
<span>* </span>OTP (One Time Password)
</label>
<input
name="otp"
id="authorizer-verify-otp"
className={`${styles['form-input-field']} ${
errorData.otp ? styles['input-error-content'] : null
}`}
placeholder="e.g.- AB123C"
type="password"
value={formData.otp || ''}
onChange={(e) => onInputChange('otp', e.target.value)}
/>
{errorData.otp && (
<div className={styles['form-input-error']}>{errorData.otp}</div>
)}
</div>
)}
<div className={styles['styled-form-group']}>
<label
className={styles['form-input-label']}
Expand Down
11 changes: 10 additions & 1 deletion src/components/AuthorizerRoot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@ export const AuthorizerRoot: FC<{
onSignup?: (data: AuthToken | void) => void;
onMagicLinkLogin?: (data: any) => void;
onForgotPassword?: (data: any) => void;
onPasswordReset?: () => void;
roles?: string[];
}> = ({ onLogin, onSignup, onMagicLinkLogin, onForgotPassword, roles }) => {
}> = ({
onLogin,
onSignup,
onMagicLinkLogin,
onForgotPassword,
onPasswordReset,
roles,
}) => {
const [view, setView] = useState(Views.Login);
const { config } = useAuthorizer();
const searchParams = new URLSearchParams(
Expand Down Expand Up @@ -84,6 +92,7 @@ export const AuthorizerRoot: FC<{
<AuthorizerForgotPassword
setView={setView}
onForgotPassword={onForgotPassword}
onPasswordReset={onPasswordReset}
urlProps={urlProps}
/>
)}
Expand Down
Loading

0 comments on commit bd6ee6c

Please sign in to comment.