From 571e06738787c691ba1e741b0de4fe15f5ae42c2 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Mon, 21 Oct 2024 17:08:03 +0200 Subject: [PATCH] Last fixes according to review --- ...tingsDevelopersWebhookUsageGraphEffect.tsx | 14 ++++-- .../useAnalyticsTinybirdJwt.test.tsx | 47 +++++++++++++++++++ .../webhook/hooks/useAnalyticsTinybirdJwt.ts | 14 +++++- .../developers/webhook/hooks/useGraphData.tsx | 3 +- .../analytics/analytics.module.ts | 17 +------ .../analytics/analytics.service.ts | 9 ++-- .../environment/environment-variables.ts | 4 -- 7 files changed, 78 insertions(+), 30 deletions(-) create mode 100644 packages/twenty-front/src/modules/settings/developers/webhook/hooks/__tests__/useAnalyticsTinybirdJwt.test.tsx diff --git a/packages/twenty-front/src/modules/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraphEffect.tsx b/packages/twenty-front/src/modules/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraphEffect.tsx index 6d4fd06dc0cf..322ec64cf3ab 100644 --- a/packages/twenty-front/src/modules/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraphEffect.tsx +++ b/packages/twenty-front/src/modules/settings/developers/webhook/components/SettingsDevelopersWebhookUsageGraphEffect.tsx @@ -1,6 +1,6 @@ import { useGraphData } from '@/settings/developers/webhook/hooks/useGraphData'; import { webhookGraphDataState } from '@/settings/developers/webhook/states/webhookGraphDataState'; -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { useSetRecoilState } from 'recoil'; type SettingsDevelopersWebhookUsageGraphEffectProps = { @@ -11,14 +11,18 @@ export const SettingsDevelopersWebhookUsageGraphEffect = ({ webhookId, }: SettingsDevelopersWebhookUsageGraphEffectProps) => { const setWebhookGraphData = useSetRecoilState(webhookGraphDataState); + const [isLoaded, setIsLoaded] = useState(false); const { fetchGraphData } = useGraphData(webhookId); useEffect(() => { - fetchGraphData('7D').then((graphInput) => { - setWebhookGraphData(graphInput); - }); - }, [fetchGraphData, setWebhookGraphData, webhookId]); + if (!isLoaded) { + fetchGraphData('7D').then((graphInput) => { + setWebhookGraphData(graphInput); + }); + setIsLoaded(true); + } + }, [fetchGraphData, isLoaded, setWebhookGraphData, webhookId]); return <>; }; diff --git a/packages/twenty-front/src/modules/settings/developers/webhook/hooks/__tests__/useAnalyticsTinybirdJwt.test.tsx b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/__tests__/useAnalyticsTinybirdJwt.test.tsx new file mode 100644 index 000000000000..70eb919a137e --- /dev/null +++ b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/__tests__/useAnalyticsTinybirdJwt.test.tsx @@ -0,0 +1,47 @@ +import { renderHook } from '@testing-library/react'; + +import { CurrentUser, currentUserState } from '@/auth/states/currentUserState'; +import { useAnalyticsTinybirdJwt } from '@/settings/developers/webhook/hooks/useAnalyticsTinybirdJwt'; +import { act } from 'react'; +import { useSetRecoilState } from 'recoil'; +import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; + +const Wrapper = getJestMetadataAndApolloMocksWrapper({ + apolloMocks: [], +}); + +describe('useAnalyticsTinybirdJwt', () => { + it('should return the analytics jwt token', async () => { + const { result } = renderHook( + () => { + const setCurrentUserState = useSetRecoilState(currentUserState); + + return { + useAnalyticsTinybirdJwt: useAnalyticsTinybirdJwt(), + setCurrentUserState, + }; + }, + { wrapper: Wrapper }, + ); + + act(() => { + result.current.setCurrentUserState({ + analyticsTinybirdJwt: 'jwt', + } as CurrentUser); + }); + + expect(result.current.useAnalyticsTinybirdJwt).toBe('jwt'); + + act(() => { + result.current.setCurrentUserState(null); + }); + + expect(result.current.useAnalyticsTinybirdJwt).toBeUndefined(); + + act(() => { + result.current.setCurrentUserState({} as CurrentUser); + }); + + expect(result.current.useAnalyticsTinybirdJwt).toBeUndefined(); + }); +}); diff --git a/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useAnalyticsTinybirdJwt.ts b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useAnalyticsTinybirdJwt.ts index adaa625cd815..67fbf1760268 100644 --- a/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useAnalyticsTinybirdJwt.ts +++ b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useAnalyticsTinybirdJwt.ts @@ -1,8 +1,18 @@ import { useRecoilValue } from 'recoil'; import { currentUserState } from '@/auth/states/currentUserState'; +import { isNull } from '@sniptt/guards'; -export const useAnalyticsTinybirdJwt = (): string | null | undefined => { +export const useAnalyticsTinybirdJwt = (): string | undefined => { const currentUser = useRecoilValue(currentUserState); - return currentUser?.analyticsTinybirdJwt; + + if (!currentUser) { + return undefined; + } + + if (isNull(currentUser.analyticsTinybirdJwt)) { + return undefined; + } + + return currentUser.analyticsTinybirdJwt; }; diff --git a/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useGraphData.tsx b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useGraphData.tsx index a3ebafd3a24d..d141d82734b5 100644 --- a/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useGraphData.tsx +++ b/packages/twenty-front/src/modules/settings/developers/webhook/hooks/useGraphData.tsx @@ -2,6 +2,7 @@ import { useAnalyticsTinybirdJwt } from '@/settings/developers/webhook/hooks/use import { fetchGraphDataOrThrow } from '@/settings/developers/webhook/utils/fetchGraphDataOrThrow'; import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar'; import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar'; +import { isUndefined } from '@sniptt/guards'; export const useGraphData = (webhookId: string) => { const { enqueueSnackBar } = useSnackBar(); @@ -10,7 +11,7 @@ export const useGraphData = (webhookId: string) => { windowLengthGraphOption: '7D' | '1D' | '12H' | '4H', ) => { try { - if (typeof analyticsTinybirdJwt !== 'string') { + if (isUndefined(analyticsTinybirdJwt)) { throw new Error('No analyticsTinybirdJwt found'); } diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts index 20e4b585efea..3897a136e5d2 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.module.ts @@ -1,33 +1,20 @@ import { HttpModule } from '@nestjs/axios'; import { Module } from '@nestjs/common'; -import { JwtModule as NestJwtModule } from '@nestjs/jwt'; -import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { JwtModule } from 'src/engine/core-modules/jwt/jwt.module'; import { AnalyticsResolver } from './analytics.resolver'; import { AnalyticsService } from './analytics.service'; const TINYBIRD_BASE_URL = 'https://api.eu-central-1.aws.tinybird.co/v0'; -const InternalTinybirdJwtModule = NestJwtModule.registerAsync({ - useFactory: async (environmentService: EnvironmentService) => { - return { - secret: environmentService.get('TINYBIRD_GENERATE_JWT_TOKEN'), - signOptions: { - expiresIn: environmentService.get('TINYBIRD_TOKEN_EXPIRES_IN'), - }, - }; - }, - inject: [EnvironmentService], -}); - @Module({ providers: [AnalyticsResolver, AnalyticsService], imports: [ + JwtModule, HttpModule.register({ baseURL: TINYBIRD_BASE_URL, }), - InternalTinybirdJwtModule, ], exports: [AnalyticsService], }) diff --git a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts index 78796b2c677e..49980b54902b 100644 --- a/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts +++ b/packages/twenty-server/src/engine/core-modules/analytics/analytics.service.ts @@ -1,10 +1,10 @@ import { HttpService } from '@nestjs/axios'; import { Injectable, Logger } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; import { AxiosRequestConfig } from 'axios'; import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service'; +import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service'; type CreateEventInput = { action: string; @@ -17,9 +17,9 @@ export class AnalyticsService { private readonly defaultDatasource = 'event'; constructor( + private readonly jwtWrapperService: JwtWrapperService, private readonly environmentService: EnvironmentService, private readonly httpService: HttpService, - private readonly jwtService: JwtService, ) {} async create( @@ -104,6 +104,9 @@ export class AnalyticsService { ], }; - return this.jwtService.sign(payload); + return this.jwtWrapperService.sign(payload, { + secret: this.environmentService.get('TINYBIRD_GENERATE_JWT_TOKEN'), + expiresIn: '7d', + }); } } diff --git a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts b/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts index da4490fe2142..03b0d234e1fe 100644 --- a/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts +++ b/packages/twenty-server/src/engine/core-modules/environment/environment-variables.ts @@ -101,10 +101,6 @@ export class EnvironmentVariables { @ValidateIf((env) => env.ANALYTICS_ENABLED) TINYBIRD_WORKSPACE_UUID: string; - @IsString() - @ValidateIf((env) => env.ANALYTICS_ENABLED) - TINYBIRD_TOKEN_EXPIRES_IN: string; - @IsString() @ValidateIf((env) => env.ANALYTICS_ENABLED) TINYBIRD_GENERATE_JWT_TOKEN: string;