diff --git a/src/containers/Auth/Auth.tsx b/src/containers/Auth/Auth.tsx index f31702810..047b9f716 100644 --- a/src/containers/Auth/Auth.tsx +++ b/src/containers/Auth/Auth.tsx @@ -14,6 +14,7 @@ import styles from './Auth.module.css'; import axios from 'axios'; import { ORGANIZATION_NAME } from 'config'; import setLogs from 'config/logs'; +import { checkOrgStatus } from 'services/AuthService'; export interface AuthProps { pageTitle: string; @@ -57,11 +58,15 @@ export const Auth = ({ const [loading, setLoading] = useState(false); const { t } = useTranslation(); const [orgName, setOrgName] = useState('Glific'); + const [status, setStatus] = useState(''); useEffect(() => { axios .post(ORGANIZATION_NAME) - .then(({ data }) => setOrgName(data?.data?.name)) + .then(({ data }) => { + setOrgName(data?.data?.name); + setStatus(data?.data?.status); + }) .catch((error) => setLogs(`orgName error ${JSON.stringify(error)}`, error)); }, []); @@ -72,6 +77,10 @@ export const Auth = ({ } }, [loading, errorMessage]); + useEffect(() => { + checkOrgStatus(status); + }, [status]); + const boxClass = [styles.Box]; const boxTitleClass = [styles.BoxTitle]; let buttonClass = styles.AuthButton; diff --git a/src/containers/Auth/Login/Login.test.tsx b/src/containers/Auth/Login/Login.test.tsx index afc1b9458..b34f9b74d 100644 --- a/src/containers/Auth/Login/Login.test.tsx +++ b/src/containers/Auth/Login/Login.test.tsx @@ -11,11 +11,11 @@ import { getCurrentUserInvalidRoleQuery, } from 'mocks/User'; -import { getOrganizationServicesQuery } from 'mocks/Organization'; +import { getOrganizationServicesQuery, getOrganizationStatus } from 'mocks/Organization'; import { Login } from './Login'; -const mocks = [getCurrentUserQuery, getOrganizationServicesQuery]; +const mocks = [getCurrentUserQuery, getOrganizationServicesQuery, getOrganizationStatus('ACTIVE')]; vi.mock('axios'); vi.mock('pino-logflare', () => ({ @@ -24,7 +24,7 @@ vi.mock('pino-logflare', () => ({ })); const mockedAxios = axios as any; -const wrapper = ( +const wrapper = (mocks: any) => ( @@ -58,7 +58,7 @@ describe('', () => { const successPromise = vi.fn(() => Promise.resolve(responseData)); mockedAxios.post.mockImplementation(() => successPromise()); - const { findByTestId } = render(wrapper); + const { findByTestId } = render(wrapper(mocks)); const authContainer = await findByTestId('AuthContainer'); expect(authContainer).toHaveTextContent('Login to your account'); }); @@ -72,7 +72,7 @@ describe('', () => { const successPromise = vi.fn(() => Promise.resolve(responseData)); mockedAxios.post.mockImplementation(() => successPromise()); - const { container } = render(wrapper); + const { container } = render(wrapper(mocks)); await userAction(container); @@ -88,7 +88,7 @@ describe('', () => { const rejectPromise = vi.fn(() => Promise.reject(errorMessage)); const localStorageSpy = vi.spyOn(Storage.prototype, 'setItem'); mockedAxios.post.mockImplementationOnce(() => rejectPromise()); - const { container } = render(wrapper); + const { container } = render(wrapper(mocks)); await userAction(container); diff --git a/src/containers/Auth/Login/Login.tsx b/src/containers/Auth/Login/Login.tsx index 04a025b39..6a8e7678c 100644 --- a/src/containers/Auth/Login/Login.tsx +++ b/src/containers/Auth/Login/Login.tsx @@ -21,6 +21,7 @@ import { setUserRolePermissions } from 'context/role'; import setLogs from 'config/logs'; import { GET_ORGANIZATION_SERVICES } from 'graphql/queries/Organization'; import { Auth } from '../Auth'; +import { setErrorMessage } from 'common/notification'; const notApprovedMsg = 'Your account is not approved yet. Please contact your organization admin.'; @@ -40,17 +41,17 @@ export const Login = () => { // get the information on current user const [getCurrentUser, { data: userData, error: userError }] = useLazyQuery(GET_CURRENT_USER); - const [getOrganizationServices, { data: organizationData }] = + const [getOrganizationServices, { data: organizationServicesData }] = useLazyQuery(GET_ORGANIZATION_SERVICES); useEffect(() => { - if (userData && organizationData) { + if (userData && organizationServicesData) { const { user } = userData.currentUser; const userCopy = JSON.parse(JSON.stringify(user)); userCopy.roles = user.accessRoles; // set the current user object setUserSession(JSON.stringify(userCopy)); - setOrganizationServices(JSON.stringify(organizationData.organizationServices)); + setOrganizationServices(JSON.stringify(organizationServicesData.organizationServices)); // get the roles const { accessRoles } = userData.currentUser.user; @@ -86,7 +87,7 @@ export const Login = () => { if (userError) { accessDenied(); } - }, [userData, userError, setAuthenticated, organizationData]); + }, [userData, userError, setAuthenticated, organizationServicesData]); const formFields = [ { @@ -126,9 +127,14 @@ export const Login = () => { setAuthSession(response.data.data); }) .catch((error) => { - setAuthError(t('Invalid phone or password.')); + if (error?.response?.status === 403) { + setErrorMessage(error?.response?.data?.error); + setAuthError(' '); + } else if (error?.response?.data?.error) { + setAuthError(error?.response?.data?.error?.message); + } // add log's - setLogs(`phoneNumber:${values.phoneNumber} URL:${USER_SESSION}`, 'info'); + // setLogs(`phoneNumber:${values.phoneNumber} URL:${USER_SESSION}`, 'info'); setLogs(error, 'error'); }); }; diff --git a/src/containers/OrganizationList/OrganizationList.tsx b/src/containers/OrganizationList/OrganizationList.tsx index 3bd4f4326..0a6661075 100644 --- a/src/containers/OrganizationList/OrganizationList.tsx +++ b/src/containers/OrganizationList/OrganizationList.tsx @@ -73,6 +73,7 @@ export const OrganizationList = ({ { id: 'INACTIVE', label:
Inactive
}, { id: 'APPROVED', label: 'Approved' }, { id: 'ACTIVE', label: 'Active' }, + { id: 'FORCED_SUSPENSION', label: 'Forced Suspension' }, { id: 'SUSPENDED', label: 'Suspended' }, { id: 'READY_TO_DELETE', label:
Ready to delete
}, ]; diff --git a/src/graphql/queries/Organization.ts b/src/graphql/queries/Organization.ts index f7bb384f6..a2391dc61 100644 --- a/src/graphql/queries/Organization.ts +++ b/src/graphql/queries/Organization.ts @@ -41,6 +41,7 @@ export const GET_ORGANIZATION = gql` signaturePhrase newcontactFlowId optinFlowId + status } } } diff --git a/src/mocks/Organization.tsx b/src/mocks/Organization.tsx index b8a5d7cff..c0c83cea6 100644 --- a/src/mocks/Organization.tsx +++ b/src/mocks/Organization.tsx @@ -50,6 +50,12 @@ export const getOrganizationQuery = [ flowId: 2, startTime: '12:31:27', }, + regxFlow: { + __typename: 'RegxFlow', + flowId: '1', + regx: 'unique_regex', + regxOpt: null, + }, setting: { lowBalanceThreshold: '10', criticalBalanceThreshold: '5', @@ -60,6 +66,7 @@ export const getOrganizationQuery = [ contact: { phone: 911111111111, }, + status: 'ACTIVE', }, }, }, @@ -99,6 +106,12 @@ export const getOrganizationQuery = [ flowId: 2, startTime: '12:31:27', }, + regxFlow: { + __typename: 'RegxFlow', + flowId: '1', + regx: 'unique_regex', + regxOpt: null, + }, setting: { lowBalanceThreshold: '10', criticalBalanceThreshold: '5', @@ -109,6 +122,7 @@ export const getOrganizationQuery = [ contact: { phone: 911111111111, }, + status: 'ACTIVE', }, }, }, @@ -154,7 +168,14 @@ export const getOrganizationQuery = [ criticalBalanceThreshold: '5', sendWarningMail: false, }, + regxFlow: { + __typename: 'RegxFlow', + flowId: '1', + regx: 'unique_regex', + regxOpt: null, + }, signaturePhrase: 'Please change me, NOW!', + status: 'ACTIVE', }, }, }, @@ -200,11 +221,18 @@ export const getOrganizationSettings = { criticalBalanceThreshold: '5', sendWarningMail: false, }, + regxFlow: { + __typename: 'RegxFlow', + flowId: '1', + regx: 'unique_regex', + regxOpt: null, + }, name: 'Glific', signaturePhrase: 'Sample text', contact: { phone: 911111111111, }, + status: 'ACTIVE', }, }, }, @@ -225,6 +253,7 @@ export const getOrganizationServicesQuery = { ticketingEnabled: true, autoTranslationEnabled: true, whatsappGroupEnabled: true, + llm4devEnabled: true, }, }, }, @@ -848,3 +877,60 @@ export const OrganizationStateMock = { }, }, }; + +export const getOrganizationStatus = (status: string) => ({ + request: { + query: GET_ORGANIZATION, + }, + result: { + data: { + organization: { + organization: { + defaultLanguage: { id: 1, label: 'English (United States)' }, + activeLanguages: [ + { + id: 1, + label: 'English (United States)', + }, + ], + id: 1, + newcontactFlowId: '5', + optinFlowId: '2', + outOfOffice: { + enabled: true, + defaultFlowId: 1, + enabledDays: [ + { enabled: true, id: 1 }, + { enabled: true, id: 2 }, + { enabled: true, id: 3 }, + { enabled: true, id: 4 }, + { enabled: true, id: 5 }, + { enabled: false, id: 6 }, + { enabled: false, id: 7 }, + ], + endTime: '12:30:27', + flowId: 2, + startTime: '12:31:27', + }, + regxFlow: { + __typename: 'RegxFlow', + flowId: '1', + regx: 'unique_regex', + regxOpt: null, + }, + setting: { + lowBalanceThreshold: '10', + criticalBalanceThreshold: '5', + sendWarningMail: false, + }, + name: 'Glific', + signaturePhrase: 'Sample text', + contact: { + phone: 911111111111, + }, + status, + }, + }, + }, + }, +}); diff --git a/src/services/AuthService.tsx b/src/services/AuthService.tsx index 50913b129..c136573ab 100644 --- a/src/services/AuthService.tsx +++ b/src/services/AuthService.tsx @@ -1,4 +1,5 @@ import axios from 'axios'; +import { setErrorMessage } from 'common/notification'; import { RENEW_TOKEN, VITE_GLIFIC_AUTHENTICATION_API } from 'config'; import setLogs from 'config/logs'; @@ -291,3 +292,27 @@ export const setAuthHeaders = () => { return { xmlSend, fetch, xmlOpen }; }; + +export const checkOrgStatus = (status: any) => { + if (status === 'suspended') { + setErrorMessage( + { + message: + 'Your account is suspended or paused by your team. In case of any concerns, please reach out to us on support@glific.org.', + }, + 'Account Suspended' + ); + return false; + } else if (status === 'forced_suspension') { + setErrorMessage( + { + message: + 'Your account has been suspended or paused due to a pending payment from your team. Kindly make the payment at your earliest convenience to resume your account. In case of any concerns, please reach out to us on support@glific.org.', + }, + 'Account Suspended' + ); + return false; + } + + return true; +};