From 94c6e897264ba54ae52a0f187b6d6e05f643d977 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Fri, 20 Oct 2023 06:31:56 -0700 Subject: [PATCH] chore: replace endpoint to licenses.info (#30697) --- apps/meteor/client/hooks/useLicense.ts | 6 +- .../hooks/useAdministrationItems.spec.tsx | 47 +++++++------- .../client/views/admin/info/LicenseCard.tsx | 63 +++++++++++-------- .../client/views/hooks/useUpgradeTabParams.ts | 10 +-- apps/meteor/ee/server/api/licenses.ts | 12 ++-- .../tests/end-to-end/api/20-licenses.js | 12 ++-- packages/rest-typings/src/v1/licenses.ts | 2 +- 7 files changed, 80 insertions(+), 72 deletions(-) diff --git a/apps/meteor/client/hooks/useLicense.ts b/apps/meteor/client/hooks/useLicense.ts index 0f568d9bd5cc..1549b431eeb7 100644 --- a/apps/meteor/client/hooks/useLicense.ts +++ b/apps/meteor/client/hooks/useLicense.ts @@ -3,8 +3,8 @@ import { useEndpoint, usePermission } from '@rocket.chat/ui-contexts'; import type { UseQueryResult } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query'; -export const useLicense = (): UseQueryResult> => { - const getLicenses = useEndpoint('GET', '/v1/licenses.get'); +export const useLicense = (): UseQueryResult> => { + const getLicenses = useEndpoint('GET', '/v1/licenses.info'); const canViewLicense = usePermission('view-privileged-setting'); return useQuery( @@ -13,7 +13,7 @@ export const useLicense = (): UseQueryResult { const { result, waitFor } = renderHook(() => useAdministrationItems(), { wrapper: mockAppRoot() - .withEndpoint('GET', '/v1/licenses.get', () => ({ - licenses: [ - { - modules: ['testModule'], - meta: { trial: false }, - } as any, - ], + .withEndpoint('GET', '/v1/licenses.info', () => ({ + license: { + // @ts-expect-error this is a mock + license: { activeModules: ['testModule'] }, + trial: false, + }, })) .withEndpoint('GET', '/v1/cloud.registrationStatus', () => ({ registrationStatus: { @@ -25,19 +24,21 @@ it('should not show upgrade item if has license and not have trial', async () => }); await waitFor(() => !!(result.all.length > 1)); - expect(result.current.length).toEqual(1); + + expect(result.current[0]).toEqual( + expect.objectContaining({ + id: 'workspace', + }), + ); }); it('should return an upgrade item if not have license or if have a trial', async () => { const { result, waitFor } = renderHook(() => useAdministrationItems(), { wrapper: mockAppRoot() - .withEndpoint('GET', '/v1/licenses.get', () => ({ - licenses: [ - { - modules: [], - } as any, - ], + .withEndpoint('GET', '/v1/licenses.info', () => ({ + // @ts-expect-error this is a mock + license: {}, })) .withEndpoint('GET', '/v1/cloud.registrationStatus', () => ({ registrationStatus: { @@ -62,12 +63,9 @@ it('should return an upgrade item if not have license or if have a trial', async it('should return omnichannel item if has `view-livechat-manager` permission ', async () => { const { result, waitFor } = renderHook(() => useAdministrationItems(), { wrapper: mockAppRoot() - .withEndpoint('GET', '/v1/licenses.get', () => ({ - licenses: [ - { - modules: [], - } as any, - ], + .withEndpoint('GET', '/v1/licenses.info', () => ({ + // @ts-expect-error this is a mock + license: {}, })) .withEndpoint('GET', '/v1/cloud.registrationStatus', () => ({ registrationStatus: { @@ -90,12 +88,9 @@ it('should return omnichannel item if has `view-livechat-manager` permission ', it('should show administration item if has at least one admin permission', async () => { const { result, waitFor } = renderHook(() => useAdministrationItems(), { wrapper: mockAppRoot() - .withEndpoint('GET', '/v1/licenses.get', () => ({ - licenses: [ - { - modules: [], - } as any, - ], + .withEndpoint('GET', '/v1/licenses.info', () => ({ + // @ts-expect-error this is a mock + license: {}, })) .withEndpoint('GET', '/v1/cloud.registrationStatus', () => ({ registrationStatus: { diff --git a/apps/meteor/client/views/admin/info/LicenseCard.tsx b/apps/meteor/client/views/admin/info/LicenseCard.tsx index bccbddaa6db7..8aab636f4720 100644 --- a/apps/meteor/client/views/admin/info/LicenseCard.tsx +++ b/apps/meteor/client/views/admin/info/LicenseCard.tsx @@ -19,15 +19,7 @@ const LicenseCard = (): ReactElement => { const isAirGapped = true; - const { data, isError, isLoading } = useLicense(); - - const { modules = [] } = isLoading || isError || !data?.licenses?.length ? {} : data?.licenses[0]; - - const hasEngagement = modules.includes('engagement-dashboard'); - const hasOmnichannel = modules.includes('livechat-enterprise'); - const hasAuditing = modules.includes('auditing'); - const hasCannedResponses = modules.includes('canned-responses'); - const hasReadReceipts = modules.includes('message-read-receipt'); + const request = useLicense(); const handleApplyLicense = useMutableCallback(() => setModal( @@ -41,6 +33,37 @@ const LicenseCard = (): ReactElement => { ), ); + if (request.isLoading || request.isError) { + return ( + + {t('License')} + + + + + + + {t('Features')} + + + + + + + + + + ); + } + + const { activeModules } = request.data.license; + + const hasEngagement = activeModules.includes('engagement-dashboard'); + const hasOmnichannel = activeModules.includes('livechat-enterprise'); + const hasAuditing = activeModules.includes('auditing'); + const hasCannedResponses = activeModules.includes('canned-responses'); + const hasReadReceipts = activeModules.includes('message-read-receipt'); + return ( {t('License')} @@ -51,22 +74,12 @@ const LicenseCard = (): ReactElement => { {t('Features')} - {isLoading ? ( - <> - - - - - - ) : ( - <> - - - - - - - )} + + + + + + diff --git a/apps/meteor/client/views/hooks/useUpgradeTabParams.ts b/apps/meteor/client/views/hooks/useUpgradeTabParams.ts index 65dd4cb1e396..1d152b08d5b9 100644 --- a/apps/meteor/client/views/hooks/useUpgradeTabParams.ts +++ b/apps/meteor/client/views/hooks/useUpgradeTabParams.ts @@ -1,4 +1,3 @@ -import type { ILicenseV2, ILicenseV3 } from '@rocket.chat/license'; import { useSetting } from '@rocket.chat/ui-contexts'; import { format } from 'date-fns'; @@ -14,14 +13,11 @@ export const useUpgradeTabParams = (): { tabType: UpgradeTabVariant | false; tri const { data: registrationStatusData, isSuccess: isSuccessRegistrationStatus } = useRegistrationStatus(); const registered = registrationStatusData?.registrationStatus?.workspaceRegistered ?? false; - const hasValidLicense = licensesData?.licenses.some((license) => license.modules.length > 0) ?? false; + const hasValidLicense = Boolean(licensesData?.license?.license ?? false); const hadExpiredTrials = cloudWorkspaceHadTrial ?? false; - const licenses = (licensesData?.licenses || []) as (Partial & { modules: string[] })[]; - - const trialLicense = licenses.find(({ meta, information }) => information?.trial ?? meta?.trial); - const isTrial = Boolean(trialLicense); - const trialEndDateStr = trialLicense?.information?.visualExpiration || trialLicense?.meta?.trialEnd || trialLicense?.cloudMeta?.trialEnd; + const isTrial = Boolean(licensesData?.license?.trial); + const trialEndDateStr = licensesData?.license?.license?.information?.visualExpiration; const trialEndDate = trialEndDateStr ? format(new Date(trialEndDateStr), 'yyyy-MM-dd') : undefined; const upgradeTabType = getUpgradeTabType({ diff --git a/apps/meteor/ee/server/api/licenses.ts b/apps/meteor/ee/server/api/licenses.ts index b7ac3ba81e9c..a2e7a75b072a 100644 --- a/apps/meteor/ee/server/api/licenses.ts +++ b/apps/meteor/ee/server/api/licenses.ts @@ -5,12 +5,15 @@ import { check } from 'meteor/check'; import { API } from '../../../app/api/server/api'; import { hasPermissionAsync } from '../../../app/authorization/server/functions/hasPermission'; +import { apiDeprecationLogger } from '../../../app/lib/server/lib/deprecationWarningLogger'; API.v1.addRoute( 'licenses.get', { authRequired: true }, { async get() { + apiDeprecationLogger.endpoint(this.request.route, '7.0.0', this.response, ' Use licenses.info instead.'); + if (!(await hasPermissionAsync(this.userId, 'view-privileged-setting'))) { return API.v1.unauthorized(); } @@ -31,9 +34,9 @@ API.v1.addRoute( const unrestrictedAccess = await hasPermissionAsync(this.userId, 'view-privileged-setting'); const loadCurrentValues = unrestrictedAccess && Boolean(this.queryParams.loadValues); - const data = await License.getInfo({ limits: unrestrictedAccess, license: unrestrictedAccess, currentValues: loadCurrentValues }); + const license = await License.getInfo({ limits: unrestrictedAccess, license: unrestrictedAccess, currentValues: loadCurrentValues }); - return API.v1.success({ data }); + return API.v1.success({ license }); }, }, ); @@ -81,8 +84,9 @@ API.v1.addRoute( { authOrAnonRequired: true }, { get() { - const isEnterpriseEdtion = License.hasValidLicense(); - return API.v1.success({ isEnterprise: isEnterpriseEdtion }); + apiDeprecationLogger.endpoint(this.request.route, '7.0.0', this.response, ' Use licenses.info instead.'); + const isEnterpriseEdition = License.hasValidLicense(); + return API.v1.success({ isEnterprise: isEnterpriseEdition }); }, }, ); diff --git a/apps/meteor/tests/end-to-end/api/20-licenses.js b/apps/meteor/tests/end-to-end/api/20-licenses.js index 302011addef9..9088e4e9e1d9 100644 --- a/apps/meteor/tests/end-to-end/api/20-licenses.js +++ b/apps/meteor/tests/end-to-end/api/20-licenses.js @@ -126,9 +126,9 @@ describe('licenses', function () { .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('data').and.to.be.an('object'); - expect(res.body.data).to.not.have.property('license'); - expect(res.body.data).to.have.property('tags').and.to.be.an('array'); + expect(res.body).to.have.property('license').and.to.be.an('object'); + expect(res.body.license).to.not.have.property('license'); + expect(res.body.license).to.have.property('tags').and.to.be.an('array'); }) .end(done); }); @@ -140,11 +140,11 @@ describe('licenses', function () { .expect(200) .expect((res) => { expect(res.body).to.have.property('success', true); - expect(res.body).to.have.property('data').and.to.be.an('object'); + expect(res.body).to.have.property('license').and.to.be.an('object'); if (process.env.IS_EE) { - expect(res.body.data).to.have.property('license').and.to.be.an('object'); + expect(res.body.license).to.have.property('license').and.to.be.an('object'); } - expect(res.body.data).to.have.property('tags').and.to.be.an('array'); + expect(res.body.license).to.have.property('tags').and.to.be.an('array'); }) .end(done); diff --git a/packages/rest-typings/src/v1/licenses.ts b/packages/rest-typings/src/v1/licenses.ts index d229ca49f1fc..4eb1ac196840 100644 --- a/packages/rest-typings/src/v1/licenses.ts +++ b/packages/rest-typings/src/v1/licenses.ts @@ -45,7 +45,7 @@ export type LicensesEndpoints = { }; '/v1/licenses.info': { GET: (params: licensesInfoProps) => { - data: LicenseInfo; + license: LicenseInfo; }; }; '/v1/licenses.add': {