From f9dc84fca1e27069d735eaf450d0c8356b65e668 Mon Sep 17 00:00:00 2001 From: Ole Martin Pettersen Date: Wed, 31 Jan 2024 15:03:40 +0100 Subject: [PATCH] =?UTF-8?q?improvement:=20better=20handling=20of=20signin?= =?UTF-8?q?=20errors=20=F0=9F=8C=B1=20#1173?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/components/Markdown/Markdown.tsx | 19 ++++++++++++ client/components/Markdown/index.ts | 2 ++ client/components/Markdown/types.ts | 3 ++ client/components/index.ts | 1 + client/i18n/en-GB.json | 5 ++-- client/i18n/nb.json | 2 +- client/i18n/nn.json | 2 +- client/pages/Home/Home.tsx | 19 ++++-------- .../Home/LoginError/LoginError.module.scss | 10 +++++++ client/pages/Home/LoginError/LoginError.tsx | 30 +++++++++++++++++++ client/pages/Home/LoginError/index.ts | 2 ++ client/pages/Home/LoginError/types.ts | 4 +++ client/pages/Home/useHome.ts | 7 +++-- server/middleware/passport/errors.ts | 19 ++++++++++-- server/routes/auth.ts | 8 +++-- 15 files changed, 109 insertions(+), 24 deletions(-) create mode 100644 client/components/Markdown/Markdown.tsx create mode 100644 client/components/Markdown/index.ts create mode 100644 client/components/Markdown/types.ts create mode 100644 client/pages/Home/LoginError/LoginError.module.scss create mode 100644 client/pages/Home/LoginError/LoginError.tsx create mode 100644 client/pages/Home/LoginError/index.ts create mode 100644 client/pages/Home/LoginError/types.ts diff --git a/client/components/Markdown/Markdown.tsx b/client/components/Markdown/Markdown.tsx new file mode 100644 index 000000000..31df6c810 --- /dev/null +++ b/client/components/Markdown/Markdown.tsx @@ -0,0 +1,19 @@ +import React, { FC } from 'react' +import ReactMarkdown from 'react-markdown' +import rehypeRaw from 'rehype-raw' +import rehypeSanitize from 'rehype-sanitize' +import { IMarkdownProps } from './types' + +/** + * Renders markdown text as HTML using ReactMarkdown with plugins + * `rehypeRaw` and `rehypeSanitize`. + * + * @param props - The props for the Markdown component. + */ +export const Markdown: FC = (props) => { + return ( + + {props.text} + + ) +} diff --git a/client/components/Markdown/index.ts b/client/components/Markdown/index.ts new file mode 100644 index 000000000..3e0ca4da1 --- /dev/null +++ b/client/components/Markdown/index.ts @@ -0,0 +1,2 @@ +export * from './Markdown' +export * from './types' diff --git a/client/components/Markdown/types.ts b/client/components/Markdown/types.ts new file mode 100644 index 000000000..ee420754b --- /dev/null +++ b/client/components/Markdown/types.ts @@ -0,0 +1,3 @@ +export interface IMarkdownProps { + text: string +} diff --git a/client/components/index.ts b/client/components/index.ts index efff7824b..15fa5222b 100644 --- a/client/components/index.ts +++ b/client/components/index.ts @@ -33,3 +33,4 @@ export * from './SubText' export * from './Toast' export * from './UserColumn' export * from './UserMessage' +export * from './Markdown' diff --git a/client/i18n/en-GB.json b/client/i18n/en-GB.json index fa5ea03d0..d1894bb97 100644 --- a/client/i18n/en-GB.json +++ b/client/i18n/en-GB.json @@ -496,7 +496,7 @@ "googleSignInText": "Sign in with Google", "activeDirectory": "Azure AD", "google": "Google", - "signInDisabledMessage": "Sign in is currently disabled. Please hold on.", + "signInDisabledText": "Sign in is currently disabled. Please hold on.", "error": "Error", "uiThemeLabel": "Theme", "light-theme": "Light theme", @@ -547,7 +547,8 @@ "projectTagCopiedToClipboard": "The project tag **{{tag}}** was copied to the clipboard.", "outlookCategoryError": "There was an error creating the category in Outlook. If you just created it, it might take some moments before it shows up here.", "tagFieldLabel": "Tag", - "ignoredHours": "Ignored hours" + "ignoredHours": "Ignored hours", + "signInDisabledMessage": "We'" }, "navigation": { "TimesheetPage": "Timesheet", diff --git a/client/i18n/nb.json b/client/i18n/nb.json index 94d9b0e93..7da754715 100644 --- a/client/i18n/nb.json +++ b/client/i18n/nb.json @@ -496,7 +496,7 @@ "googleSignInText": "Logg på med Google", "activeDirectory": "Azure AD", "google": "Google", - "signInDisabledMessage": "Pålogging er for øyeblikket deaktivert. \nVennligst vent.", + "signInDisabledText": "Pålogging er for øyeblikket deaktivert. \nVennligst vent.", "error": "Feilmelding", "uiThemeLabel": "Fargetema", "dark-theme": "Mørkt tema", diff --git a/client/i18n/nn.json b/client/i18n/nn.json index 74376d00d..e39f4567b 100644 --- a/client/i18n/nn.json +++ b/client/i18n/nn.json @@ -498,7 +498,7 @@ "googleSignInText": "Logg på med Google", "activeDirectory": "Azure AD", "google": "Google", - "signInDisabledMessage": "Pålogging er for øyeblikket deaktivert. \nVennligst vent.", + "signInDisabledText": "Pålogging er for øyeblikket deaktivert. \nVennligst vent.", "error": "Feilmelding", "uiThemeLabel": "Fargetema", "dark-theme": "Mørkt tema", diff --git a/client/pages/Home/Home.tsx b/client/pages/Home/Home.tsx index d00aa806f..74ffbf1bb 100644 --- a/client/pages/Home/Home.tsx +++ b/client/pages/Home/Home.tsx @@ -1,5 +1,4 @@ import { Button } from '@fluentui/react-components' -import { UserMessage } from 'components' import { Logo } from 'components/Logo' import { PageComponent } from 'pages/types' import React from 'react' @@ -7,6 +6,7 @@ import { useTranslation } from 'react-i18next' import { Redirect } from 'react-router-dom' import _ from 'underscore' import styles from './Home.module.scss' +import { LoginError } from './LoginError' import { useAuthProviders } from './useAuthProviders' import { useHome } from './useHome' @@ -17,7 +17,7 @@ import { useHome } from './useHome' */ export const Home: PageComponent = () => { const { t } = useTranslation() - const { error, subscription, redirectPage } = useHome() + const { loginError, subscription, redirectPage } = useHome() const providers = useAuthProviders() if (redirectPage) { @@ -27,20 +27,13 @@ export const Home: PageComponent = () => { return (
- {error && ( - + {loginError && ( + )} {_.isEmpty(Object.keys(providers)) && ( - + )} - {!subscription && !error && ( + {!subscription && !loginError && (
{Object.keys(providers).map((key) => ( +
+ ) +} + +LoginError.displayName = 'LoginError' +LoginError.className = styles.loginError diff --git a/client/pages/Home/LoginError/index.ts b/client/pages/Home/LoginError/index.ts new file mode 100644 index 000000000..62ad64bb7 --- /dev/null +++ b/client/pages/Home/LoginError/index.ts @@ -0,0 +1,2 @@ +export * from './LoginError' +export * from './types' diff --git a/client/pages/Home/LoginError/types.ts b/client/pages/Home/LoginError/types.ts new file mode 100644 index 000000000..2849e4aed --- /dev/null +++ b/client/pages/Home/LoginError/types.ts @@ -0,0 +1,4 @@ +export interface ILoginErrorProps { + text: string + message?: string +} diff --git a/client/pages/Home/useHome.ts b/client/pages/Home/useHome.ts index 78309d947..bc8c7e974 100644 --- a/client/pages/Home/useHome.ts +++ b/client/pages/Home/useHome.ts @@ -8,7 +8,7 @@ export function useHome() { const { user, subscription } = useAppContext() const location = useLocation<{ prevPath: string }>() const urlSearchParameters = new URLSearchParams(document.location.search) - const error = + const loginError: Error = urlSearchParameters.get('error') && JSON.parse(atob(urlSearchParameters.get('error'))) const redirectPage = @@ -17,9 +17,10 @@ export function useHome() { location.state?.prevPath === undefined ? user.startPage : null + return { - error, + loginError, subscription, redirectPage - } as const + } } diff --git a/server/middleware/passport/errors.ts b/server/middleware/passport/errors.ts index 3c43bd386..9bb11f7d1 100644 --- a/server/middleware/passport/errors.ts +++ b/server/middleware/passport/errors.ts @@ -27,6 +27,9 @@ export class SigninError extends Error { } } +/** + * No OID found error + */ export const NO_OID_FOUND = new SigninError( '0f8fc199', 'Sorry to break it to you..', @@ -34,13 +37,19 @@ export const NO_OID_FOUND = new SigninError( 'BlockedSite' ) +/** + * Tenant not enrolled error + */ export const TENANT_NOT_ENROLLED = new SigninError( 'de72e4da', 'Your company is not enrolled in did', - 'Please contactdid@puzzlepart.com for more information.', + 'We\'re currently accepting new pilot customers. Please contact did@puzzlepart.com for more information.', 'Phone' ) +/** + * User not enrolled error + */ export const USER_NOT_ENROLLED = new SigninError( 'cee991f0', 'I promised to keep it a secret...', @@ -49,13 +58,19 @@ export const USER_NOT_ENROLLED = new SigninError( 'Sad' ) -export const SIGNIN_FAILED = new SigninError( +/** + * Generic sign in failed error + */ +export const GENERIC_SIGNIN_FAILED = new SigninError( 'e0666582', 'An error occured signing you in', 'Sorry, we were not able to sign you in right now, and we are not really sure why!

It can help to clear your browser cache.', 'Dislike' ) +/** + * User account disabled error + */ export const USER_ACCOUNT_DISABLED = new SigninError( 'e0666582', 'An error occured signing you in', diff --git a/server/routes/auth.ts b/server/routes/auth.ts index 1fb0d4eec..e046a34ec 100644 --- a/server/routes/auth.ts +++ b/server/routes/auth.ts @@ -10,7 +10,10 @@ import { NextFunction, Request, Response, Router } from 'express' import passport from 'passport' import _ from 'underscore' import url from 'url' -import { SigninError, SIGNIN_FAILED } from '../middleware/passport/errors' +import { + SigninError, + GENERIC_SIGNIN_FAILED +} from '../middleware/passport/errors' import { environment } from '../utils' const auth = Router() @@ -40,7 +43,8 @@ export const authCallbackHandler = (request: Request, response: Response, next: NextFunction) => { passport.authenticate(strategy, (error: Error, user: Express.User) => { if (error || !user) { - const _error = error instanceof SigninError ? error : SIGNIN_FAILED + const _error = + error instanceof SigninError ? error : GENERIC_SIGNIN_FAILED return response.redirect( url.format({ pathname: '/',