Skip to content

Commit

Permalink
fix: Login page breaking when handling not expected errors (#31804)
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriellsh authored Feb 29, 2024
1 parent 8a59f10 commit 8b10c6c
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 18 deletions.
5 changes: 5 additions & 0 deletions .changeset/quick-cheetahs-help.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@rocket.chat/web-ui-registration": patch
---

fixed the login page crashing when receiving unexpected errors
36 changes: 24 additions & 12 deletions packages/web-ui-registration/src/LoginForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ const LOGIN_SUBMIT_ERRORS = {
},
} as const;

export type LoginErrors = keyof typeof LOGIN_SUBMIT_ERRORS | 'totp-canceled';
export type LoginErrors = keyof typeof LOGIN_SUBMIT_ERRORS | 'totp-canceled' | string;

export type LoginErrorState = [error: LoginErrors, message?: string] | undefined;

export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRouter }): ReactElement => {
const {
Expand All @@ -72,7 +74,7 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute

const { t } = useTranslation();
const formLabelId = useUniqueId();
const [errorOnSubmit, setErrorOnSubmit] = useState<LoginErrors | undefined>(undefined);
const [errorOnSubmit, setErrorOnSubmit] = useState<LoginErrorState>(undefined);
const isResetPasswordAllowed = useSetting('Accounts_PasswordReset');
const login = useLoginWithPassword();
const showFormLogin = useSetting('Accounts_ShowFormLogin');
Expand All @@ -92,11 +94,11 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute
}

if ('error' in error && error.error !== 403) {
setErrorOnSubmit(error.error);
setErrorOnSubmit([error.error, error.reason]);
return;
}

setErrorOnSubmit('user-not-found');
setErrorOnSubmit(['user-not-found']);
},
});

Expand All @@ -110,18 +112,28 @@ export const LoginForm = ({ setLoginRoute }: { setLoginRoute: DispatchLoginRoute
}
}, [errorOnSubmit]);

const renderErrorOnSubmit = (error: LoginErrors) => {
const renderErrorOnSubmit = ([error, message]: Exclude<LoginErrorState, undefined>) => {
if (error in LOGIN_SUBMIT_ERRORS) {
const { type, i18n } = LOGIN_SUBMIT_ERRORS[error as Exclude<LoginErrors, string>];
return (
<Callout id={`${usernameId}-error`} aria-live='assertive' type={type}>
{t(i18n)}
</Callout>
);
}

if (error === 'totp-canceled') {
return null;
}

const { type, i18n } = LOGIN_SUBMIT_ERRORS[error];

return (
<Callout id={`${usernameId}-error`} aria-live='assertive' type={type}>
{t(i18n)}
</Callout>
);
if (message) {
return (
<Callout id={`${usernameId}-error`} aria-live='assertive' type='danger'>
{message}
</Callout>
);
}
return null;
};

if (errors.usernameOrEmail?.type === 'invalid-email') {
Expand Down
4 changes: 2 additions & 2 deletions packages/web-ui-registration/src/LoginServices.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import { useLoginServices, useSetting } from '@rocket.chat/ui-contexts';
import type { Dispatch, ReactElement, SetStateAction } from 'react';
import { useTranslation } from 'react-i18next';

import type { LoginErrors } from './LoginForm';
import type { LoginErrorState } from './LoginForm';
import LoginServicesButton from './LoginServicesButton';

const LoginServices = ({
disabled,
setError,
}: {
disabled?: boolean;
setError: Dispatch<SetStateAction<LoginErrors | undefined>>;
setError: Dispatch<SetStateAction<LoginErrorState>>;
}): ReactElement | null => {
const { t } = useTranslation();
const services = useLoginServices();
Expand Down
8 changes: 4 additions & 4 deletions packages/web-ui-registration/src/LoginServicesButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useLoginWithService, useTranslation } from '@rocket.chat/ui-contexts';
import type { ReactElement, SetStateAction, Dispatch } from 'react';
import { useCallback } from 'react';

import type { LoginErrors } from './LoginForm';
import type { LoginErrorState, LoginErrors } from './LoginForm';

const LoginServicesButton = <T extends LoginService>({
buttonLabelText,
Expand All @@ -19,17 +19,17 @@ const LoginServicesButton = <T extends LoginService>({
}: T & {
className?: string;
disabled?: boolean;
setError?: Dispatch<SetStateAction<LoginErrors | undefined>>;
setError?: Dispatch<SetStateAction<LoginErrorState>>;
}): ReactElement => {
const t = useTranslation();
const handler = useLoginWithService({ service, buttonLabelText, ...props });

const handleOnClick = useCallback(() => {
handler().catch((e: { error?: LoginErrors }) => {
handler().catch((e: { error?: LoginErrors; reason?: string }) => {
if (!e.error || typeof e.error !== 'string') {
return;
}
setError?.(e.error);
setError?.([e.error, e.reason]);
});
}, [handler, setError]);

Expand Down

0 comments on commit 8b10c6c

Please sign in to comment.