Deprecate dummy enterprise key 1/2 (#20890)
Remove usage of hasValidEnterpriseKey in FE (replaced by hasValidSignedEnterpriseKey) To avoid breaking change at deploy time, we will wait until after this has been deployed in prod, to remove hasValidEnterpriseKey in the BE.
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -2,12 +2,12 @@ import { gql, InMemoryCache } from '@apollo/client';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import fetchMock, { enableFetchMocks } from 'jest-fetch-mock';
|
||||
|
||||
import { ApolloFactory, type Options } from '@/apollo/services/apollo.factory';
|
||||
import { CUSTOM_WORKSPACE_APPLICATION_MOCK } from '@/object-metadata/hooks/__tests__/constants/CustomWorkspaceApplicationMock.test.constant';
|
||||
import {
|
||||
AUTO_SELECT_FAST_MODEL_ID,
|
||||
AUTO_SELECT_SMART_MODEL_ID,
|
||||
} from 'twenty-shared/constants';
|
||||
import { ApolloFactory, type Options } from '@/apollo/services/apollo.factory';
|
||||
import { CUSTOM_WORKSPACE_APPLICATION_MOCK } from '@/object-metadata/hooks/__tests__/constants/CustomWorkspaceApplicationMock.test.constant';
|
||||
import { WorkspaceActivationStatus } from '~/generated-metadata/graphql';
|
||||
|
||||
enableFetchMocks();
|
||||
@@ -67,7 +67,6 @@ const mockWorkspace = {
|
||||
isGoogleAuthBypassEnabled: false,
|
||||
isPasswordAuthBypassEnabled: false,
|
||||
isMicrosoftAuthBypassEnabled: false,
|
||||
hasValidEnterpriseKey: false,
|
||||
hasActivatedAndValidEnterpriseKey: false,
|
||||
hasValidSignedEnterpriseKey: false,
|
||||
hasValidEnterpriseValidityToken: false,
|
||||
|
||||
@@ -26,7 +26,6 @@ export type CurrentWorkspace = Pick<
|
||||
| 'isPasswordAuthEnabled'
|
||||
| 'isPasswordAuthBypassEnabled'
|
||||
| 'isCustomDomainEnabled'
|
||||
| 'hasValidEnterpriseKey'
|
||||
| 'hasValidSignedEnterpriseKey'
|
||||
| 'hasValidEnterpriseValidityToken'
|
||||
| 'subdomain'
|
||||
|
||||
-2
@@ -6,7 +6,6 @@ import { InformationBannerBillingSubscriptionPaused } from '@/information-banner
|
||||
import { InformationBannerEndTrialPeriod } from '@/information-banner/components/billing/InformationBannerEndTrialPeriod';
|
||||
import { InformationBannerFailPaymentInfo } from '@/information-banner/components/billing/InformationBannerFailPaymentInfo';
|
||||
import { InformationBannerNoBillingSubscription } from '@/information-banner/components/billing/InformationBannerNoBillingSubscription';
|
||||
import { InformationBannerInvalidEnterpriseKey } from '@/information-banner/components/enterprise/InformationBannerInvalidEnterpriseKey';
|
||||
import { InformationBannerMaintenance } from '@/information-banner/components/maintenance/InformationBannerMaintenance';
|
||||
import { InformationBannerReconnectAccountEmailAliases } from '@/information-banner/components/reconnect-account/InformationBannerReconnectAccountEmailAliases';
|
||||
import { InformationBannerReconnectAccountInsufficientPermissions } from '@/information-banner/components/reconnect-account/InformationBannerReconnectAccountInsufficientPermissions';
|
||||
@@ -65,7 +64,6 @@ export const InformationBannerWrapper = () => {
|
||||
return (
|
||||
<StyledInformationBannerWrapper>
|
||||
<InformationBannerMaintenance />
|
||||
<InformationBannerInvalidEnterpriseKey />
|
||||
{isAccountSyncEnabled && (
|
||||
<InformationBannerReconnectAccountInsufficientPermissions />
|
||||
)}
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { InformationBanner } from '@/information-banner/components/InformationBanner';
|
||||
import { informationBannerIsOpenComponentState } from '@/information-banner/states/informationBannerIsOpenComponentState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconKey } from 'twenty-ui/display';
|
||||
|
||||
const COMPONENT_INSTANCE_ID = 'information-banner-invalid-enterprise-key';
|
||||
|
||||
export const InformationBannerInvalidEnterpriseKey = () => {
|
||||
const { t } = useLingui();
|
||||
const navigate = useNavigate();
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
|
||||
const setInformationBannerIsOpen = useSetAtomComponentState(
|
||||
informationBannerIsOpenComponentState,
|
||||
COMPONENT_INSTANCE_ID,
|
||||
);
|
||||
|
||||
const hasInvalidKey =
|
||||
currentWorkspace?.hasValidEnterpriseKey === true &&
|
||||
currentWorkspace?.hasValidSignedEnterpriseKey !== true &&
|
||||
currentWorkspace?.hasValidEnterpriseValidityToken !== true;
|
||||
|
||||
if (!hasInvalidKey) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<InformationBanner
|
||||
componentInstanceId={COMPONENT_INSTANCE_ID}
|
||||
variant="secondary"
|
||||
message={t`Your enterprise key is no longer valid. Activate a new key to continue using enterprise features.`}
|
||||
buttonTitle={t`Activate`}
|
||||
buttonIcon={IconKey}
|
||||
buttonOnClick={() =>
|
||||
navigate(getSettingsPath(SettingsPath.AdminPanelEnterprise))
|
||||
}
|
||||
onClose={() => setInformationBannerIsOpen(false)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
-1
@@ -161,7 +161,6 @@ export const responseData = {
|
||||
allowImpersonation: false,
|
||||
activationStatus: 'active',
|
||||
isPublicInviteLinkEnabled: false,
|
||||
hasValidEnterpriseKey: false,
|
||||
hasValidSignedEnterpriseKey: false,
|
||||
hasValidEnterpriseValidityToken: false,
|
||||
isGoogleAuthEnabled: true,
|
||||
|
||||
+8
-8
@@ -4,19 +4,19 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import { SettingsPath } from 'twenty-shared/types';
|
||||
|
||||
import { useSnackBarOnQueryError } from '@/apollo/hooks/useSnackBarOnQueryError';
|
||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||
import { SettingsCard } from '@/settings/components/SettingsCard';
|
||||
import { SettingsSSOIdentitiesProvidersListCardWrapper } from '@/settings/security/components/SSO/SettingsSSOIdentitiesProvidersListCardWrapper';
|
||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||
import { useSnackBarOnQueryError } from '@/apollo/hooks/useSnackBarOnQueryError';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useAtomState } from '@/ui/utilities/state/jotai/hooks/useAtomState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useQuery } from '@apollo/client/react';
|
||||
import { styled } from '@linaria/react';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { useEffect } from 'react';
|
||||
import { getSettingsPath } from 'twenty-shared/utils';
|
||||
import { IconKey } from 'twenty-ui/display';
|
||||
import { useQuery } from '@apollo/client/react';
|
||||
import { GetSsoIdentityProvidersDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
const StyledLinkContainer = styled.div<{ isDisabled: boolean }>`
|
||||
@@ -42,7 +42,7 @@ export const SettingsSSOIdentitiesProvidersListCard = () => {
|
||||
error: ssoError,
|
||||
} = useQuery(GetSsoIdentityProvidersDocument, {
|
||||
fetchPolicy: 'network-only',
|
||||
skip: currentWorkspace?.hasValidEnterpriseKey === false,
|
||||
skip: currentWorkspace?.hasValidSignedEnterpriseKey === false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -55,12 +55,12 @@ export const SettingsSSOIdentitiesProvidersListCard = () => {
|
||||
|
||||
return loading || !SSOIdentitiesProviders.length ? (
|
||||
<StyledLinkContainer
|
||||
isDisabled={currentWorkspace?.hasValidEnterpriseKey !== true}
|
||||
isDisabled={currentWorkspace?.hasValidSignedEnterpriseKey !== true}
|
||||
>
|
||||
<Link to={getSettingsPath(SettingsPath.NewSSOIdentityProvider)}>
|
||||
<SettingsCard
|
||||
title={t`Add SSO Identity Provider`}
|
||||
disabled={currentWorkspace?.hasValidEnterpriseKey !== true}
|
||||
disabled={currentWorkspace?.hasValidSignedEnterpriseKey !== true}
|
||||
Icon={<IconKey />}
|
||||
/>
|
||||
</Link>
|
||||
|
||||
@@ -60,7 +60,6 @@ export const USER_QUERY_FRAGMENT = gql`
|
||||
isPasswordAuthBypassEnabled
|
||||
subdomain
|
||||
customDomain
|
||||
hasValidEnterpriseKey
|
||||
hasValidSignedEnterpriseKey
|
||||
hasValidEnterpriseValidityToken
|
||||
workspaceCustomApplication {
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Separator } from '@/settings/components/Separator';
|
||||
import { SettingsEnterpriseFeatureGateCard } from '@/settings/components/SettingsEnterpriseFeatureGateCard';
|
||||
import { SettingsOptionCardContentButton } from '@/settings/components/SettingsOptions/SettingsOptionCardContentButton';
|
||||
import { SettingsOptionCardContentCounter } from '@/settings/components/SettingsOptions/SettingsOptionCardContentCounter';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsRoleDefaultRole } from '@/settings/roles/components/SettingsRolesDefaultRole';
|
||||
import { SettingsRolesQueryEffect } from '@/settings/roles/components/SettingsRolesQueryEffect';
|
||||
@@ -20,7 +21,6 @@ import { SettingsSecurityAuthBypassOptionsList } from '@/settings/security/compo
|
||||
import { SettingsSecurityAuthProvidersOptionsList } from '@/settings/security/components/SettingsSecurityAuthProvidersOptionsList';
|
||||
import { SettingsSecurityEditableProfileFields } from '@/settings/security/components/SettingsSecurityEditableProfileFields';
|
||||
import { SSOIdentitiesProvidersState } from '@/settings/security/states/SSOIdentitiesProvidersState';
|
||||
import { SettingsOptionCardContentToggle } from '@/settings/components/SettingsOptions/SettingsOptionCardContentToggle';
|
||||
import { ToggleImpersonate } from '@/settings/workspace/components/ToggleImpersonate';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/components/SubMenuTopBarContainer';
|
||||
@@ -193,7 +193,8 @@ export const SettingsSecurity = () => {
|
||||
!hasDirectAuthEnabled &&
|
||||
hasBypassProviderAvailable;
|
||||
|
||||
const hasEnterpriseAccess = currentWorkspace?.hasValidEnterpriseKey === true;
|
||||
const hasEnterpriseAccess =
|
||||
currentWorkspace?.hasValidSignedEnterpriseKey === true;
|
||||
const isEventLogsEnabled = hasEnterpriseAccess && isClickHouseConfigured;
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { type CurrentUserWorkspace } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { CUSTOM_WORKSPACE_APPLICATION_MOCK } from '@/object-metadata/hooks/__tests__/constants/CustomWorkspaceApplicationMock.test.constant';
|
||||
import { type WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
import {
|
||||
AUTO_SELECT_FAST_MODEL_ID,
|
||||
AUTO_SELECT_SMART_MODEL_ID,
|
||||
} from 'twenty-shared/constants';
|
||||
import { type CurrentUserWorkspace } from '@/auth/states/currentUserWorkspaceState';
|
||||
import { CUSTOM_WORKSPACE_APPLICATION_MOCK } from '@/object-metadata/hooks/__tests__/constants/CustomWorkspaceApplicationMock.test.constant';
|
||||
import { type WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||
import {
|
||||
OnboardingStatus,
|
||||
PermissionFlagType,
|
||||
|
||||
-25
@@ -286,31 +286,6 @@ describe('EnterprisePlanService', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// hasValidEnterpriseKey now means "has any ENTERPRISE_KEY configured"
|
||||
describe('hasValidEnterpriseKey', () => {
|
||||
it('should return true when signed enterprise key is valid', async () => {
|
||||
await setupValidState();
|
||||
|
||||
expect(service.hasValidEnterpriseKey()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true with unsigned legacy key', async () => {
|
||||
setupEnterpriseKey('some-legacy-key');
|
||||
mockCryptoVerify.mockReturnValue(false);
|
||||
appTokenFindOneMock.mockResolvedValue(null);
|
||||
await service.onModuleInit();
|
||||
|
||||
expect(service.hasValidEnterpriseKey()).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false when no key is configured', async () => {
|
||||
setupEnterpriseKey(undefined);
|
||||
await service.onModuleInit();
|
||||
|
||||
expect(service.hasValidEnterpriseKey()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isValid', () => {
|
||||
it('should return true when validity token is valid', async () => {
|
||||
await setupValidState();
|
||||
|
||||
-9
@@ -142,19 +142,10 @@ export class EnterprisePlanService implements OnModuleInit {
|
||||
return false;
|
||||
}
|
||||
|
||||
hasValidEnterpriseKey(): boolean {
|
||||
return this.hasValidSignedEnterpriseKey() || this.checkLegacyKey();
|
||||
}
|
||||
|
||||
isValid(): boolean {
|
||||
return this.hasValidEnterpriseValidityToken();
|
||||
}
|
||||
|
||||
private checkLegacyKey(): boolean {
|
||||
// temporary
|
||||
return isDefined(this.twentyConfigService.get('ENTERPRISE_KEY'));
|
||||
}
|
||||
|
||||
isValidEnterpriseKeyFormat(key: string): boolean {
|
||||
return this.verifyJwt<EnterpriseKeyPayload>(key) !== null;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ export class WorkspaceResolver {
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
hasValidEnterpriseKey(): boolean {
|
||||
return this.enterprisePlanService.hasValidEnterpriseKey();
|
||||
return this.enterprisePlanService.hasValidSignedEnterpriseKey();
|
||||
}
|
||||
|
||||
@ResolveField(() => Boolean)
|
||||
|
||||
Reference in New Issue
Block a user