Simplify infrastructure to one container

This commit is contained in:
Charles Bochet
2023-03-06 16:15:46 +01:00
parent 2ddb191556
commit c2833cad53
61 changed files with 2211 additions and 1992 deletions

View File

@ -1,57 +0,0 @@
import { useAuth0 } from '@auth0/auth0-react';
import { useState, useEffect } from 'react';
import jwt from 'jwt-decode';
import { TokenPayload } from '../interfaces/TokenPayload.interface';
const useIsNotLoggedIn = () => {
const { isAuthenticated, isLoading } = useAuth0();
const hasAccessToken = localStorage.getItem('accessToken');
return (!isAuthenticated || !hasAccessToken) && !isLoading;
};
const redirectIfNotLoggedIn = () => {
const isNotLoggedIn = useIsNotLoggedIn();
const { loginWithRedirect } = useAuth0();
if (isNotLoggedIn) {
loginWithRedirect();
}
};
const useGetUserEmailFromToken = (): string | undefined => {
const token = localStorage.getItem('accessToken');
const payload: TokenPayload | undefined = token ? jwt(token) : undefined;
if (!payload) {
return;
}
return payload['https://hasura.io/jwt/claims']['x-hasura-user-email'];
};
const useGetAccessToken = () => {
const [loading, setLoading] = useState(false);
const [token, setToken] = useState('');
const { getAccessTokenSilently } = useAuth0();
useEffect(() => {
const fetchToken = async () => {
setLoading(true);
const accessToken = await getAccessTokenSilently();
localStorage.setItem('accessToken', accessToken);
setLoading(false);
setToken(accessToken);
};
fetchToken();
}, []);
return { loading, token };
};
export {
useIsNotLoggedIn,
useGetAccessToken,
redirectIfNotLoggedIn,
useGetUserEmailFromToken,
};

View File

@ -1,129 +0,0 @@
import { renderHook } from '@testing-library/react';
import {
useIsNotLoggedIn,
useGetUserEmailFromToken,
} from '../AuthenticationHooks';
import { useAuth0 } from '@auth0/auth0-react';
import { mocked } from 'jest-mock';
jest.mock('@auth0/auth0-react');
const mockedUseAuth0 = mocked(useAuth0, true);
const user = {
email: 'johndoe@me.com',
email_verified: true,
sub: 'google-oauth2|12345678901234',
};
describe('useIsNotLoggedIn', () => {
beforeEach(() => {
window.localStorage.clear();
jest.resetModules();
});
it('returns false if auth0 is loading', () => {
mockedUseAuth0.mockReturnValue({
isAuthenticated: false,
user,
logout: jest.fn(),
loginWithRedirect: jest.fn(),
getAccessTokenWithPopup: jest.fn(),
getAccessTokenSilently: jest.fn(),
getIdTokenClaims: jest.fn(),
loginWithPopup: jest.fn(),
handleRedirectCallback: jest.fn(),
isLoading: true,
});
const { result } = renderHook(() => useIsNotLoggedIn());
const isNotLoggedIn = result.current;
expect(isNotLoggedIn).toBe(false);
});
it('returns false if token is not there', () => {
mockedUseAuth0.mockReturnValue({
isAuthenticated: false,
user,
logout: jest.fn(),
loginWithRedirect: jest.fn(),
getAccessTokenWithPopup: jest.fn(),
getAccessTokenSilently: jest.fn(),
getIdTokenClaims: jest.fn(),
loginWithPopup: jest.fn(),
handleRedirectCallback: jest.fn(),
isLoading: false,
});
const { result } = renderHook(() => useIsNotLoggedIn());
const isNotLoggedIn = result.current;
expect(isNotLoggedIn).toBe(true);
});
it('returns false if token is there but user is not connected on auth0', () => {
mockedUseAuth0.mockReturnValue({
isAuthenticated: false,
user,
logout: jest.fn(),
loginWithRedirect: jest.fn(),
getAccessTokenWithPopup: jest.fn(),
getAccessTokenSilently: jest.fn(),
getIdTokenClaims: jest.fn(),
loginWithPopup: jest.fn(),
handleRedirectCallback: jest.fn(),
isLoading: false,
});
window.localStorage.setItem('accessToken', 'token');
const { result } = renderHook(() => useIsNotLoggedIn());
const isNotLoggedIn = result.current;
expect(isNotLoggedIn).toBe(true);
});
it('returns false if token is there and user is connected on auth0', () => {
mockedUseAuth0.mockReturnValue({
isAuthenticated: true,
user,
logout: jest.fn(),
loginWithRedirect: jest.fn(),
getAccessTokenWithPopup: jest.fn(),
getAccessTokenSilently: jest.fn(),
getIdTokenClaims: jest.fn(),
loginWithPopup: jest.fn(),
handleRedirectCallback: jest.fn(),
isLoading: false,
});
window.localStorage.setItem('accessToken', 'token');
const { result } = renderHook(() => useIsNotLoggedIn());
const isNotLoggedIn = result.current;
expect(isNotLoggedIn).toBe(false);
});
});
describe('useGetUserEmailFromToken', () => {
beforeEach(() => {
window.localStorage.clear();
jest.resetModules();
});
it('returns undefined if token is not there', () => {
const { result } = renderHook(() => useGetUserEmailFromToken());
const email = result.current;
expect(email).toBe(undefined);
});
it('returns email if token is there', () => {
window.localStorage.setItem(
'accessToken',
'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im1FQXZiR0dFNjJ4S25mTFNxNHQ0dCJ9.eyJodHRwczovL2hhc3VyYS5pby9qd3QvY2xhaW1zIjp7IngtaGFzdXJhLWFsbG93ZWQtcm9sZXMiOlsidXNlciJdLCJ4LWhhc3VyYS1kZWZhdWx0LXJvbGUiOiJ1c2VyIiwieC1oYXN1cmEtdXNlci1lbWFpbCI6ImNoYXJsZXNAb3VpaGVscC50d2VudHkuY29tIiwieC1oYXN1cmEtdXNlci1pZCI6Imdvb2dsZS1vYXV0aDJ8MTE4MjM1ODk3NDQ2OTIwNTQ3NzMzIn0sImlzcyI6Imh0dHBzOi8vdHdlbnR5LWRldi5ldS5hdXRoMC5jb20vIiwic3ViIjoiZ29vZ2xlLW9hdXRoMnwxMTgyMzU4OTc0NDY5MjA1NDc3MzMiLCJhdWQiOlsiaGFzdXJhLWRldiIsImh0dHBzOi8vdHdlbnR5LWRldi5ldS5hdXRoMC5jb20vdXNlcmluZm8iXSwiaWF0IjoxNjc1MzYyNzY0LCJleHAiOjE2NzU0NDkxNjQsImF6cCI6IlM2ZXoyUFdUdUFsRncydjdxTFBWb2hmVXRseHc4QlBhIiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCJ9.DseeSqYzNlYVQfuicoK8fK1Z6b-TYNvCkRoXXYOhg1X3HDSejowUTudyrJGErkT65xMCfx8K5quof9eV8BZQixCPr670r5gAIHxHuGY_KNfHTOALe8E5VyQaoekRyDr99Qo3QxliOOlJxtmckA8FTeD6JanfVmcrqghUOIsSXXDOOzJV6eME7JErEjTQHpfxveSVbPlCmIqZ3fqDaFdKfAlUDZFhVQM8XbfubNmG4VcoMyB7H47yLdGkYvVfPO1lVg0efywQo4IfbtiqFv5CjOEqO6PG78Wfkd24bcilkf6ZuGXsA-w-0xlU089GhKF99lNI1PxvNWAaLFbqanxiEw',
);
const { result } = renderHook(() => useGetUserEmailFromToken());
expect(result.current).toBe('charles@ouihelp.twenty.com');
});
});

View File

@ -1,25 +0,0 @@
import { renderHook } from '@testing-library/react';
import { useQuery, QueryResult } from '@apollo/client';
import { useGetProfile } from '../useGetProfile';
jest.mock('@apollo/client', () => ({
useQuery: jest.fn(),
}));
describe('useGetUserEmailFromToken', () => {
beforeEach(() => {
const result: Partial<QueryResult<any>> = {
data: { users: [{ email: 'test@twenty.com' }] },
loading: false,
error: undefined,
};
(useQuery as jest.Mock).mockImplementation(() => result as QueryResult);
});
it('returns profile', () => {
const { result } = renderHook(() => useGetProfile());
const email = result.current.user?.email;
expect(email).toEqual(result.current.user?.email);
expect(useQuery).toHaveBeenCalledTimes(1);
});
});

View File

@ -1,33 +0,0 @@
import { ApolloError, useQuery } from '@apollo/client';
import { gql } from 'graphql-tag';
import { User } from '../../interfaces/user.interface';
import { useGetUserEmailFromToken } from '../AuthenticationHooks';
const GET_USER_PROFILE = gql`
query GetUserProfile($email: String!) {
users(where: { email: { _eq: $email } }, limit: 1) {
id
email
first_name
last_name
tenant {
id
name
}
}
}
`;
type ProfileResult = {
loading: boolean;
error?: ApolloError;
user?: User;
};
export const useGetProfile = (): ProfileResult => {
const email = useGetUserEmailFromToken();
const { loading, error, data } = useQuery(GET_USER_PROFILE, {
variables: { email },
});
return { loading, error, user: data?.users[0] };
};

View File

@ -1,25 +0,0 @@
import { renderHook } from '@testing-library/react';
import { useQuery, QueryResult } from '@apollo/client';
import { useGetTenantByDomain } from '../useGetTenantByDomain';
jest.mock('@apollo/client', () => ({
useQuery: jest.fn(),
}));
describe('useGetTenantByDomain', () => {
beforeEach(() => {
const result: Partial<QueryResult<any>> = {
data: { tenants: [{ domain: 'pilot.twenty.com' }] },
loading: false,
error: undefined,
};
(useQuery as jest.Mock).mockImplementation(() => result as QueryResult);
});
it('returns tenant by domain', () => {
const { result } = renderHook(() => useGetTenantByDomain());
const domain = result.current.tenant?.domain;
expect(domain).toEqual(result.current.tenant?.domain);
expect(useQuery).toHaveBeenCalledTimes(1);
});
});

View File

@ -1,31 +0,0 @@
import { ApolloError, useQuery } from '@apollo/client';
import { gql } from 'graphql-tag';
import { Tenant } from '../../interfaces/tenant.interface';
const GET_TENANT_BY_DOMAIN = gql`
query GetTenantByDomain($domain: String!) {
tenants(where: { domain: { _eq: $domain } }, limit: 1) {
auth0_client_id
domain
}
}
`;
type TenantResult = {
loading: boolean;
error?: ApolloError;
tenant?: Tenant;
};
export const useGetTenantByDomain = (): TenantResult => {
const domain = window.location.hostname;
const { loading, error, data } = useQuery(GET_TENANT_BY_DOMAIN, {
variables: { domain },
context: {
headers: {
'x-hasura-default-role': 'public',
},
},
});
return { loading, error, tenant: data?.tenants[0] };
};