From e380c598d3ce4a14df70e753db382224f64c383d Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Wed, 15 May 2024 14:03:58 +0200 Subject: [PATCH] fix: Showing the real mail address on email confirmation view (#445) * fix: Showing the real mail address on email confirmation view * chore: remove the unused hook --- .../containers/Authentication/Register.tsx | 13 +++- .../Authentication/RegisterVerify.tsx | 8 ++- .../webapp/src/hooks/query/authentication.tsx | 34 +++++++++-- packages/webapp/src/hooks/query/users.tsx | 4 +- .../webapp/src/hooks/state/authentication.tsx | 61 ++++++++++++++++++- .../authentication/authentication.actions.tsx | 24 +++++++- .../authentication/authentication.reducer.tsx | 37 +++++++++-- .../authentication/authentication.types.tsx | 7 ++- 8 files changed, 165 insertions(+), 23 deletions(-) diff --git a/packages/webapp/src/containers/Authentication/Register.tsx b/packages/webapp/src/containers/Authentication/Register.tsx index 32225c850..e787abcf8 100644 --- a/packages/webapp/src/containers/Authentication/Register.tsx +++ b/packages/webapp/src/containers/Authentication/Register.tsx @@ -9,7 +9,11 @@ import AuthInsider from '@/containers/Authentication/AuthInsider'; import { useAuthLogin, useAuthRegister } from '@/hooks/query/authentication'; import RegisterForm from './RegisterForm'; -import { RegisterSchema, transformRegisterErrorsToForm, transformRegisterToastMessages } from './utils'; +import { + RegisterSchema, + transformRegisterErrorsToForm, + transformRegisterToastMessages, +} from './utils'; import { AuthFooterLinks, AuthFooterLink, @@ -32,7 +36,7 @@ export default function RegisterUserForm() { const handleSubmit = (values, { setSubmitting, setErrors }) => { authRegisterMutate(values) - .then((response) => { + .then(() => { authLoginMutate({ crediential: values.email, password: values.password, @@ -87,7 +91,10 @@ function RegisterFooterLinks() { return ( - + {' '} + + + diff --git a/packages/webapp/src/containers/Authentication/RegisterVerify.tsx b/packages/webapp/src/containers/Authentication/RegisterVerify.tsx index a707bfdb0..46148a426 100644 --- a/packages/webapp/src/containers/Authentication/RegisterVerify.tsx +++ b/packages/webapp/src/containers/Authentication/RegisterVerify.tsx @@ -4,7 +4,7 @@ import AuthInsider from './AuthInsider'; import { AuthInsiderCard } from './_components'; import styles from './RegisterVerify.module.scss'; import { AppToaster, Stack } from '@/components'; -import { useAuthActions } from '@/hooks/state'; +import { useAuthActions, useAuthUserVerifyEmail } from '@/hooks/state'; import { useAuthSignUpVerifyResendMail } from '@/hooks/query'; import { AuthContainer } from './AuthContainer'; @@ -13,6 +13,8 @@ export default function RegisterVerify() { const { mutateAsync: resendSignUpVerifyMail, isLoading } = useAuthSignUpVerifyResendMail(); + const emailAddress = useAuthUserVerifyEmail(); + const handleResendMailBtnClick = () => { resendSignUpVerifyMail() .then(() => { @@ -38,8 +40,8 @@ export default function RegisterVerify() {

Please verify your email

- We sent an email to asdahmed@gmail.com Click the - link inside to get started. + We sent an email to {emailAddress} Click the link + inside to get started.

diff --git a/packages/webapp/src/hooks/query/authentication.tsx b/packages/webapp/src/hooks/query/authentication.tsx index 7f48d78b2..96ee23426 100644 --- a/packages/webapp/src/hooks/query/authentication.tsx +++ b/packages/webapp/src/hooks/query/authentication.tsx @@ -1,9 +1,17 @@ // @ts-nocheck import { useMutation } from 'react-query'; +import { batch } from 'react-redux'; import useApiRequest from '../useRequest'; import { setCookie } from '../../utils'; import { useRequestQuery } from '../useQueryRequest'; import t from './types'; +import { + useSetAuthToken, + useSetAuthUserId, + useSetLocale, + useSetOrganizationId, + useSetTenantId, +} from '../state'; /** * Saves the response data to cookies. @@ -24,14 +32,30 @@ function setAuthLoginCookies(data) { export const useAuthLogin = (props) => { const apiRequest = useApiRequest(); + const setAuthToken = useSetAuthToken(); + const setOrganizationId = useSetOrganizationId(); + const setUserId = useSetAuthUserId(); + const setTenantId = useSetTenantId(); + const setLocale = useSetLocale(); + return useMutation((values) => apiRequest.post('auth/login', values), { select: (res) => res.data, - onSuccess: (data) => { + onSuccess: (res) => { // Set authentication cookies. - setAuthLoginCookies(data.data); - - // Reboot the application. - window.location.reload(); + setAuthLoginCookies(res.data); + + batch(() => { + // Sets the auth metadata to global state. + setAuthToken(res.data.token); + setOrganizationId(res.data.tenant.organization_id); + setUserId(res.data.user.id); + setTenantId(res.data.tenant.id); + + if (res.data?.tenant?.metadata?.language) { + setLocale(res.data?.tenant?.metadata?.language); + } + }); + props?.onSuccess && props?.onSuccess(...args); }, ...props, }); diff --git a/packages/webapp/src/hooks/query/users.tsx b/packages/webapp/src/hooks/query/users.tsx index 646308353..00452091a 100644 --- a/packages/webapp/src/hooks/query/users.tsx +++ b/packages/webapp/src/hooks/query/users.tsx @@ -1,7 +1,7 @@ // @ts-nocheck import { useEffect } from 'react'; import { useMutation, useQueryClient } from 'react-query'; -import { useQueryTenant, useRequestQuery } from '../useQueryRequest'; +import { useRequestQuery } from '../useQueryRequest'; import useApiRequest from '../useRequest'; import { useSetFeatureDashboardMeta } from '../state/feature'; import t from './types'; @@ -143,7 +143,7 @@ export function useAuthenticatedAccount(props) { select: (response) => response.data.data, defaultData: {}, onSuccess: (data) => { - setEmailConfirmed(data.is_verified); + setEmailConfirmed(data.is_verified, data.email); }, ...props, }, diff --git a/packages/webapp/src/hooks/state/authentication.tsx b/packages/webapp/src/hooks/state/authentication.tsx index 73054c663..a39a8bc86 100644 --- a/packages/webapp/src/hooks/state/authentication.tsx +++ b/packages/webapp/src/hooks/state/authentication.tsx @@ -3,8 +3,13 @@ import { useDispatch, useSelector } from 'react-redux'; import { useCallback } from 'react'; import { isAuthenticated } from '@/store/authentication/authentication.reducer'; import { + setAuthTenantId, + setAuthToken, + setAuthUserId, setEmailConfirmed, setLogin, + setOrganizationId, + setLocale, } from '@/store/authentication/authentication.actions'; import { useQueryClient } from 'react-query'; import { removeCookie } from '@/utils'; @@ -75,6 +80,14 @@ export const useAuthUserVerified = () => { return useSelector((state) => state.authentication.verified); }; +/** + * Retrieves the user's email address. + * @returns {string} + */ +export const useAuthUserVerifyEmail = () => { + return useSelector((state) => state.authentication.verifyEmail); +}; + /** * Sets the user's email verification status. */ @@ -82,7 +95,53 @@ export const useSetAuthEmailConfirmed = () => { const dispatch = useDispatch(); return useCallback( - (verified?: boolean = true) => dispatch(setEmailConfirmed(verified)), + (verified?: boolean = true, email: string) => + dispatch(setEmailConfirmed(verified, email)), + [dispatch], + ); +}; + +export const useSetOrganizationId = () => { + const dispatch = useDispatch(); + + return useCallback( + (organizationId: string) => dispatch(setOrganizationId(organizationId)), + [dispatch], + ); +}; + +export const useSetAuthToken = () => { + const dispatch = useDispatch(); + + return useCallback( + (authToken: string) => dispatch(setAuthToken(authToken)), + [dispatch], + ); +}; + +export const useSetTenantId = () => { + const dispatch = useDispatch(); + + return useCallback( + (tenantId: string) => dispatch(setAuthTenantId(tenantId)), + [dispatch], + ); +}; + +export const useSetAuthUserId = () => { + const dispatch = useDispatch(); + + return useCallback( + (userId: string) => dispatch(setAuthUserId(userId)), + [dispatch], + ); +}; + +export const useSetLocale = () => { + const dispatch = useDispatch(); + + return useCallback( + (locale: string) => dispatch(setLocale(locale)), [dispatch], ); }; diff --git a/packages/webapp/src/store/authentication/authentication.actions.tsx b/packages/webapp/src/store/authentication/authentication.actions.tsx index daefd8f48..f7dc4d5e5 100644 --- a/packages/webapp/src/store/authentication/authentication.actions.tsx +++ b/packages/webapp/src/store/authentication/authentication.actions.tsx @@ -4,7 +4,27 @@ import t from '@/store/types'; export const setLogin = () => ({ type: t.LOGIN_SUCCESS }); export const setLogout = () => ({ type: t.LOGOUT }); export const setStoreReset = () => ({ type: t.RESET }); -export const setEmailConfirmed = (verified?: boolean) => ({ +export const setEmailConfirmed = (verified?: boolean, email?: string) => ({ type: t.SET_EMAIL_VERIFIED, - action: { verified }, + action: { verified, email }, +}); +export const setOrganizationId = (organizationId: string) => ({ + type: t.SET_ORGANIZATIOIN_ID, + action: { organizationId }, +}); +export const setAuthToken = (token: string) => ({ + type: t.SET_AUTH_TOKEN, + action: { token }, +}); +export const setAuthTenantId = (tenantId: string) => ({ + type: t.SET_TENANT_ID, + action: { tenantId }, +}); +export const setAuthUserId = (userId: string) => ({ + type: t.SET_USER_ID, + action: { userId }, +}); +export const setLocale = (locale: string) => ({ + type: t.SET_LOCALE, + action: { locale }, }); diff --git a/packages/webapp/src/store/authentication/authentication.reducer.tsx b/packages/webapp/src/store/authentication/authentication.reducer.tsx index ce56b81ec..40daaf917 100644 --- a/packages/webapp/src/store/authentication/authentication.reducer.tsx +++ b/packages/webapp/src/store/authentication/authentication.reducer.tsx @@ -9,12 +9,13 @@ import t from '@/store/types'; // Read stored data in cookies and merge it with the initial state. const initialState = { - token: getCookie('token'), - organizationId: getCookie('organization_id'), - tenantId: getCookie('tenant_id'), - userId: getCookie('authenticated_user_id'), - locale: getCookie('locale'), + token: getCookie('token') || null, + organizationId: getCookie('organization_id') || null, + tenantId: getCookie('tenant_id') || null, + userId: getCookie('authenticated_user_id') || null, + locale: getCookie('locale') || 'en', verified: true, // Let's be optimistic and assume the user's email is confirmed. + verifyEmail: null, errors: [], }; @@ -36,11 +37,35 @@ const reducerInstance = createReducer(initialState, { [t.SET_EMAIL_VERIFIED]: ( state, - payload: PayloadAction<{ verified?: boolean }>, + payload: PayloadAction<{ verified?: boolean; email?: string }>, ) => { state.verified = !isUndefined(payload.action.verified) ? payload.action.verified : true; + state.verifyEmail = payload.action.email || null; + + if (state.verified) { + state.verifyEmail = null; + } + }, + + [t.SET_AUTH_TOKEN]: (state, payload: PayloadAction<{ token: string }>) => { + state.token = payload.action.token; + }, + + [t.SET_ORGANIZATIOIN_ID]: ( + state, + payload: PayloadAction<{ organizationId: string }>, + ) => { + state.organizationId = payload.action.organizationId; + }, + + [t.SET_TENANT_ID]: (state, payload: PayloadAction<{ tenantId: string }>) => { + state.tenantId = payload.action.tenantId; + }, + + [t.SET_USER_ID]: (state, payload: PayloadAction<{ userId: string }>) => { + state.userId = payload.action.userId; }, [t.RESET]: (state) => { diff --git a/packages/webapp/src/store/authentication/authentication.types.tsx b/packages/webapp/src/store/authentication/authentication.types.tsx index f64af4652..5957493f2 100644 --- a/packages/webapp/src/store/authentication/authentication.types.tsx +++ b/packages/webapp/src/store/authentication/authentication.types.tsx @@ -7,5 +7,10 @@ export default { LOGOUT: 'LOGOUT', LOGIN_CLEAR_ERRORS: 'LOGIN_CLEAR_ERRORS', RESET: 'RESET', - SET_EMAIL_VERIFIED: 'SET_EMAIL_VERIFIED' + SET_EMAIL_VERIFIED: 'SET_EMAIL_VERIFIED', + SET_AUTH_TOKEN: 'SET_AUTH_TOKEN', + SET_ORGANIZATIOIN_ID: 'SET_ORGANIZATIOIN_ID', + SET_TENANT_ID: 'SET_TENANT_ID', + SET_USER_ID: 'SET_USER_ID', + SET_LOCALE: 'SET_LOCALE', }; \ No newline at end of file