Remove api keys from old world (#2548)
* Use apiKeyV2 for getApiKeys * Use apiKeyV2 for createApiKey * Use apiKeyV2 for getApiKey * Use apiKeyV2 to deleteapikey * Filter null revokedAt -> not working * Use apiKeyV2 to regenerate * Fix default values injected * Remove useless stuff * Fix type
This commit is contained in:
@ -1,9 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
import { DateTime } from 'luxon';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord';
|
||||
import { useFindOneObjectRecord } from '@/object-record/hooks/useFindOneObjectRecord';
|
||||
import { useUpdateOneObjectRecord } from '@/object-record/hooks/useUpdateOneObjectRecord';
|
||||
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { ApiKeyInput } from '@/settings/developers/components/ApiKeyInput';
|
||||
@ -18,11 +21,7 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import {
|
||||
useDeleteOneApiKeyMutation,
|
||||
useGetApiKeyQuery,
|
||||
useInsertOneApiKeyMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
||||
|
||||
const StyledInfo = styled.span`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
@ -41,28 +40,29 @@ const StyledInputContainer = styled.div`
|
||||
export const SettingsDevelopersApiKeyDetail = () => {
|
||||
const navigate = useNavigate();
|
||||
const { apiKeyId = '' } = useParams();
|
||||
const { triggerOptimisticEffects } = useOptimisticEffect('ApiKeyV2');
|
||||
|
||||
const setGeneratedApi = useGeneratedApiKeys();
|
||||
const [generatedApiKey] = useRecoilState(
|
||||
generatedApiKeyFamilyState(apiKeyId),
|
||||
);
|
||||
|
||||
const [deleteApiKey] = useDeleteOneApiKeyMutation();
|
||||
const [insertOneApiKey] = useInsertOneApiKeyMutation();
|
||||
const apiKeyData = useGetApiKeyQuery({
|
||||
variables: {
|
||||
apiKeyId,
|
||||
},
|
||||
}).data?.findManyApiKey[0];
|
||||
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
||||
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord({
|
||||
objectNamePlural: 'apiKeysV2',
|
||||
});
|
||||
const { updateOneObject: updateApiKey } = useUpdateOneObjectRecord({
|
||||
objectNamePlural: 'apiKeysV2',
|
||||
});
|
||||
|
||||
const { object: apiKeyData } = useFindOneObjectRecord({
|
||||
objectNameSingular: 'apiKeyV2',
|
||||
objectMetadataId: apiKeyId,
|
||||
});
|
||||
|
||||
const deleteIntegration = async (redirect = true) => {
|
||||
await deleteApiKey({
|
||||
variables: { apiKeyId },
|
||||
update: (cache) =>
|
||||
cache.evict({
|
||||
id: cache.identify({ __typename: 'ApiKey', id: apiKeyId }),
|
||||
}),
|
||||
await updateApiKey?.({
|
||||
idToUpdate: apiKeyId,
|
||||
input: { revokedAt: DateTime.now().toString() },
|
||||
});
|
||||
if (redirect) {
|
||||
navigate('/settings/developers/api-keys');
|
||||
@ -73,19 +73,23 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
||||
name: string,
|
||||
newExpiresAt: string | null,
|
||||
) => {
|
||||
return await insertOneApiKey({
|
||||
const newApiKey = await createOneApiKey?.({
|
||||
name: name,
|
||||
expiresAt: newExpiresAt,
|
||||
});
|
||||
const tokenData = await generateOneApiKeyToken({
|
||||
variables: {
|
||||
data: {
|
||||
name: name,
|
||||
expiresAt: newExpiresAt,
|
||||
id: newApiKey.createApiKeyV2.id,
|
||||
expiresAt: newApiKey.createApiKeyV2.expiresAt,
|
||||
name: newApiKey.createApiKeyV2.name, // TODO update typing to remove useless name param here
|
||||
},
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
if (data?.createOneApiKey) {
|
||||
triggerOptimisticEffects('ApiKey', [data?.createOneApiKey]);
|
||||
}
|
||||
},
|
||||
});
|
||||
return {
|
||||
id: newApiKey.createApiKeyV2.id,
|
||||
token: tokenData.data?.generateApiKeyV2Token.token,
|
||||
};
|
||||
};
|
||||
|
||||
const regenerateApiKey = async () => {
|
||||
@ -96,14 +100,9 @@ export const SettingsDevelopersApiKeyDetail = () => {
|
||||
);
|
||||
const apiKey = await createIntegration(apiKeyData.name, newExpiresAt);
|
||||
await deleteIntegration(false);
|
||||
if (apiKey.data?.createOneApiKey) {
|
||||
setGeneratedApi(
|
||||
apiKey.data.createOneApiKey.id,
|
||||
apiKey.data.createOneApiKey.token,
|
||||
);
|
||||
navigate(
|
||||
`/settings/developers/api-keys/${apiKey.data.createOneApiKey.id}`,
|
||||
);
|
||||
if (apiKey.token) {
|
||||
setGeneratedApi(apiKey.id, apiKey.token);
|
||||
navigate(`/settings/developers/api-keys/${apiKey.id}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,10 +1,13 @@
|
||||
import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { useFindManyObjectRecords } from '@/object-record/hooks/useFindManyObjectRecords';
|
||||
import { objectSettingsWidth } from '@/settings/data-model/constants/objectSettings';
|
||||
import { SettingsApiKeysFieldItemTableRow } from '@/settings/developers/components/SettingsApiKeysFieldItemTableRow';
|
||||
import { getApiKeysOptimisticEffectDefinition } from '@/settings/developers/optimistic-effect-definitions/getApiKeysOptimisticEffectDefinition';
|
||||
import { ApiFieldItem } from '@/settings/developers/types/ApiFieldItem';
|
||||
import { formatExpirations } from '@/settings/developers/utils/format-expiration';
|
||||
import { IconPlus, IconSettings } from '@/ui/display/icon';
|
||||
import { H1Title } from '@/ui/display/typography/components/H1Title';
|
||||
@ -14,7 +17,6 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
|
||||
import { Table } from '@/ui/layout/table/components/Table';
|
||||
import { TableHeader } from '@/ui/layout/table/components/TableHeader';
|
||||
import { TableRow } from '@/ui/layout/table/components/TableRow';
|
||||
import { useGetApiKeysQuery } from '~/generated/graphql';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
height: fit-content;
|
||||
@ -40,15 +42,26 @@ const StyledH1Title = styled(H1Title)`
|
||||
export const SettingsDevelopersApiKeys = () => {
|
||||
const navigate = useNavigate();
|
||||
const { registerOptimisticEffect } = useOptimisticEffect('ApiKeyV2');
|
||||
const apiKeysQuery = useGetApiKeysQuery({
|
||||
onCompleted: () => {
|
||||
const [apiKeys, setApiKeys] = useState<Array<ApiFieldItem>>([]);
|
||||
useFindManyObjectRecords({
|
||||
objectNamePlural: 'apiKeysV2',
|
||||
/*filter: { revokedAt: { eq: null } },*/
|
||||
onCompleted: (data) => {
|
||||
setApiKeys(
|
||||
formatExpirations(
|
||||
data.edges.map((apiKey) => ({
|
||||
id: apiKey.node.id,
|
||||
name: apiKey.node.name,
|
||||
expiresAt: apiKey.node.expiresAt,
|
||||
})),
|
||||
),
|
||||
);
|
||||
registerOptimisticEffect({
|
||||
variables: {},
|
||||
definition: getApiKeysOptimisticEffectDefinition,
|
||||
});
|
||||
},
|
||||
});
|
||||
const apiKeys = apiKeysQuery.data ? formatExpirations(apiKeysQuery.data) : [];
|
||||
|
||||
return (
|
||||
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
||||
|
||||
@ -2,7 +2,7 @@ import { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { useOptimisticEffect } from '@/apollo/optimistic-effect/hooks/useOptimisticEffect';
|
||||
import { useCreateOneObjectRecord } from '@/object-record/hooks/useCreateOneObjectRecord';
|
||||
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
|
||||
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
@ -15,11 +15,10 @@ import { TextInput } from '@/ui/input/components/TextInput';
|
||||
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
||||
import { useInsertOneApiKeyMutation } from '~/generated/graphql';
|
||||
import { useGenerateOneApiKeyTokenMutation } from '~/generated/graphql';
|
||||
|
||||
export const SettingsDevelopersApiKeysNew = () => {
|
||||
const [insertOneApiKey] = useInsertOneApiKeyMutation();
|
||||
const { triggerOptimisticEffects } = useOptimisticEffect('ApiKeyV2');
|
||||
const [generateOneApiKeyToken] = useGenerateOneApiKeyTokenMutation();
|
||||
const navigate = useNavigate();
|
||||
const setGeneratedApi = useGeneratedApiKeys();
|
||||
const [formValues, setFormValues] = useState<{
|
||||
@ -29,35 +28,36 @@ export const SettingsDevelopersApiKeysNew = () => {
|
||||
expirationDate: ExpirationDates[0].value,
|
||||
name: '',
|
||||
});
|
||||
|
||||
const { createOneObject: createOneApiKey } = useCreateOneObjectRecord({
|
||||
objectNamePlural: 'apiKeysV2',
|
||||
});
|
||||
const onSave = async () => {
|
||||
const apiKey = await insertOneApiKey({
|
||||
const expiresAt = formValues.expirationDate
|
||||
? DateTime.now().plus({ days: formValues.expirationDate }).toString()
|
||||
: null;
|
||||
const newApiKey = await createOneApiKey?.({
|
||||
name: formValues.name,
|
||||
expiresAt,
|
||||
});
|
||||
const tokenData = await generateOneApiKeyToken({
|
||||
variables: {
|
||||
data: {
|
||||
name: formValues.name,
|
||||
expiresAt: formValues.expirationDate
|
||||
? DateTime.now()
|
||||
.plus({ days: formValues.expirationDate })
|
||||
.toString()
|
||||
: null,
|
||||
id: newApiKey.createApiKeyV2.id,
|
||||
expiresAt: newApiKey.createApiKeyV2.expiresAt,
|
||||
name: newApiKey.createApiKeyV2.name, // TODO update typing to remove useless name param here
|
||||
},
|
||||
},
|
||||
update: (_cache, { data }) => {
|
||||
if (data?.createOneApiKey) {
|
||||
triggerOptimisticEffects('ApiKey', [data?.createOneApiKey]);
|
||||
}
|
||||
},
|
||||
});
|
||||
if (apiKey.data?.createOneApiKey) {
|
||||
if (tokenData.data?.generateApiKeyV2Token) {
|
||||
setGeneratedApi(
|
||||
apiKey.data.createOneApiKey.id,
|
||||
apiKey.data.createOneApiKey.token,
|
||||
);
|
||||
navigate(
|
||||
`/settings/developers/api-keys/${apiKey.data.createOneApiKey.id}`,
|
||||
newApiKey.createApiKeyV2.id,
|
||||
tokenData.data.generateApiKeyV2Token.token,
|
||||
);
|
||||
navigate(`/settings/developers/api-keys/${newApiKey.createApiKeyV2.id}`);
|
||||
}
|
||||
};
|
||||
const canSave = !!formValues.name;
|
||||
const canSave = !!formValues.name && createOneApiKey;
|
||||
return (
|
||||
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
||||
<SettingsPageContainer>
|
||||
|
||||
Reference in New Issue
Block a user