Skip to content

Commit

Permalink
feat(kms): add iam management on service keys
Browse files Browse the repository at this point in the history
ref: MANAGER-15238

Signed-off-by: Romain Jamet <[email protected]>
  • Loading branch information
Romain Jamet authored and vovh committed Oct 17, 2024
1 parent 60cf4e3 commit 74cc7c1
Show file tree
Hide file tree
Showing 11 changed files with 209 additions and 135 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,5 @@
"key_management_service_dashboard_dashboard_field_state_suspended": "Suspendu",
"key_management_service_dashboard_dashboard_field_state_toActivate": "À activer",
"key_management_service_dashboard_dashboard_field_state_toDelete": "À supprimer",
"key_management_service_dashboard_dashboard_field_state_toSuspend": "À suspendre",
"key_management_service_update_name_success_banner": "Le nom a été modifié avec succès.",
"key_management_service_update_name_error_banner": "La modification n'a pas été prise en compte.",
"key_management_service_dashboard_modal_input_label": "Nouveau nom d'affichage",
"key_management_service_update_name": ""
"key_management_service_dashboard_dashboard_field_state_toSuspend": "À suspendre"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useContext } from 'react';
import {
ActionMenu,
Clipboard,
Expand All @@ -10,7 +10,7 @@ import {
PageLocation,
useOvhTracking,
} from '@ovh-ux/manager-react-shell-client';
import { useNavigate, useParams } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { useTranslation } from 'react-i18next';
import { ODS_ICON_NAME, ODS_SPINNER_SIZE } from '@ovhcloud/ods-components';
import { OsdsSpinner } from '@ovhcloud/ods-components/react';
Expand All @@ -24,6 +24,7 @@ import { useOkmsServiceKeyById } from '@/data/hooks/useOkmsServiceKeys';
import { useFormattedDate } from '@/hooks/useFormattedDate';
import { useKMSServiceInfos } from '@/data/hooks/useKMSServiceInfos';
import { OkmsServiceState } from '../layout-helpers/Dashboard/okmsServiceState/OkmsServiceState.component';
import { OkmsContext } from '@/pages/dashboard';

export const DatagridCellId = (props: OKMS | OkmsAllServiceKeys) => {
return <Clipboard value={props.id} />;
Expand Down Expand Up @@ -129,12 +130,12 @@ export const DatagridStatus = (props: OkmsAllServiceKeys) => {
};

export const DatagridServiceKeyActionMenu = (props: OkmsAllServiceKeys) => {
const { okmsId } = useParams();
const okms = useContext(OkmsContext);
const { data: serviceKey, isPending } = useOkmsServiceKeyById({
okmsId,
okmsId: okms.id,
keyId: props.id,
});
const actionList = useServiceKeyActionsList(okmsId, serviceKey?.data, true);
const actionList = useServiceKeyActionsList(okms, serviceKey?.data, true);

if (isPending) {
return <></>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { OsdsIcon, OsdsButton } from '@ovhcloud/ods-components/react';
import React from 'react';
import { OsdsIcon, OsdsButton } from '@ovhcloud/ods-components/react';
import { ManagerButton } from '@ovh-ux/manager-react-components';
import {
ODS_BUTTON_SIZE,
ODS_BUTTON_TEXT_ALIGN,
Expand All @@ -9,9 +10,10 @@ import {
} from '@ovhcloud/ods-components';
import { OkmsAllServiceKeys } from '@/types/okmsServiceKey.type';
import useServiceKeyActionsList from '@/hooks/serviceKey/useServiceKeyActionsList';
import { OKMS } from '@/types/okms.type';

type ServiceKeyStateActionsProps = {
okmsId: string;
okms: OKMS;
okmsKey: OkmsAllServiceKeys;
};

Expand All @@ -23,38 +25,62 @@ const ActionsIcons = [
];

const ServiceKeyStateActions = ({
okmsId,
okms,
okmsKey,
}: ServiceKeyStateActionsProps) => {
const actionList = useServiceKeyActionsList(okmsId, okmsKey);
const actionList = useServiceKeyActionsList(okms, okmsKey);

const getActionIcon = (id: number) => {
return ActionsIcons.find((actionIcon) => actionIcon.id === id)?.icon;
};
return (
<>
{actionList.map((action) => (
<OsdsButton
key={action.id}
color={action.color}
variant={ODS_BUTTON_VARIANT.ghost}
size={ODS_BUTTON_SIZE.sm}
textAlign={ODS_BUTTON_TEXT_ALIGN.start}
onClick={action.onClick}
disabled={action.disabled || undefined}
href={action.href}
download={action.download}
>
<span slot="start">{action.label}</span>
<span slot="end">
<OsdsIcon
name={getActionIcon(action.id)}
size={ODS_ICON_SIZE.xxs}
color={action.color}
/>
</span>
</OsdsButton>
))}
{actionList.map((action) => {
return action.iamActions ? (
<ManagerButton
key={action.id}
color={action.color}
variant={ODS_BUTTON_VARIANT.ghost}
size={ODS_BUTTON_SIZE.sm}
textAlign={ODS_BUTTON_TEXT_ALIGN.start}
onClick={action.onClick}
disabled={action.disabled || undefined}
href={action.href}
download={action.download}
urn={action.urn}
iamActions={action.iamActions}
>
<span slot="start">{action.label}</span>
<span slot="end">
<OsdsIcon
name={getActionIcon(action.id)}
size={ODS_ICON_SIZE.xxs}
color={action.color}
/>
</span>
</ManagerButton>
) : (
<OsdsButton
key={action.id}
variant={ODS_BUTTON_VARIANT.ghost}
size={ODS_BUTTON_SIZE.sm}
color={action.color}
href={action.href}
download={action.download}
disabled={action.disabled || undefined}
onClick={action.onClick}
>
<span slot="start">{action.label}</span>
<span slot="end">
<OsdsIcon
name={getActionIcon(action.id)}
size={ODS_ICON_SIZE.xxs}
color={action.color}
/>
</span>
</OsdsButton>
);
})}
</>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useQuery } from '@tanstack/react-query';

import { ApiError } from '@ovh-ux/manager-core-api';
import { ErrorResponse } from '@/types/api.type';
import {
getOkmsServiceKeyResource,
Expand All @@ -16,7 +17,7 @@ import {
/* Service Key List */

export const useAllOkmsServiceKeys = (okmsId: string) => {
return useQuery({
return useQuery<{ data: OkmsAllServiceKeys[] }, ApiError>({
queryKey: getOkmsServiceKeyResourceListQueryKey(okmsId),
queryFn: () => getListingOkmsServiceKey(okmsId),
retry: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApiError, ApiResponse } from '@ovh-ux/manager-core-api';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useNotifications } from '@ovh-ux/manager-react-components';
import {
Expand Down Expand Up @@ -36,7 +35,7 @@ export const useUpdateOkmsName = ({
onError,
}: UpdateOkmsParams) => {
const queryClient = useQueryClient();
const { t } = useTranslation('key-management-service/dashboard');
const { t } = useTranslation('key-management-service/serviceKeys');
const { addError, addSuccess, clearNotifications } = useNotifications();

const {
Expand Down Expand Up @@ -65,13 +64,16 @@ export const useUpdateOkmsName = ({
queryKey: getOkmsResourceQueryKey(okmsId),
});
clearNotifications();
addSuccess(t('key_management_service_update_name_success_banner'), true);
addSuccess(
t('key_management_service_service-keys_update_name_success'),
true,
);
onSuccess?.();
},
onError: (result: ApiError) => {
clearNotifications();
addError(
t('key_management_service_update_name_error_banner', {
t('key_management_service_service-keys_update_error', {
error: result.message,
}),
true,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { describe, expect, it, vi } from 'vitest';
import { ODS_THEME_COLOR_INTENT } from '@ovhcloud/ods-common-theming';
import { renderHook } from '@testing-library/react';
import { OkmsKeyTypes, OkmsServiceKeyState } from '@/types/okmsServiceKey.type';
import {
OkmsAllServiceKeys,
OkmsKeyTypes,
OkmsServiceKeyState,
} from '@/types/okmsServiceKey.type';
import useServiceKeyActionsList from './useServiceKeyActionsList';
import { OKMS } from '@/types/okms.type';

vi.mock('react-i18next', () => ({
useTranslation: vi.fn(() => ({ t: vi.fn((key) => key) })),
Expand Down Expand Up @@ -31,13 +36,25 @@ vi.mock('@/data/hooks/useUpdateOkmsServiceKey', () => ({
}));

describe('useServiceKeyActionsList', () => {
const okmsId = 'testOkmsId';
const commonKeyProps = {
const okms: OKMS = {
iam: {
displayName: 'kms-1',
id: '1b4e7c8e-d1b8-4b46-a584-52c8b4b0225c',
urn: `urn:v1:eu:resource:okms:1b4e7c8e-d1b8-4b46-a584-52c8b4b0225c`,
},
id: '7f3a82ac-a8d8-4c2a-ab0c-f6e86ddf6a7c',
kmipEndpoint: 'eu-west-rbx.okms.ovh.net:1234',
region: 'EU_WEST_RBX',
restEndpoint: 'https://eu-west-rbx.okms.ovh.net',
swaggerEndpoint: '"https://swagger-eu-west-rbx.okms.ovh.net',
};

const commonKeyProps: Omit<OkmsAllServiceKeys, 'type' | 'state'> = {
id: 'testKeyId',
name: 'testKeyName',
keys: [] as any[],
keys: [],
createdAt: '2023-01-01T00:00:00Z',
operations: [] as any[],
operations: [],
};

const useCases = [
Expand Down Expand Up @@ -171,7 +188,7 @@ describe('useServiceKeyActionsList', () => {
useCases.forEach(({ description, okmsKey, expectedActions }) => {
it(description, () => {
const { result } = renderHook(() =>
useServiceKeyActionsList(okmsId, okmsKey),
useServiceKeyActionsList(okms, okmsKey),
);
expect(result.current).toEqual(
expect.arrayContaining(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {
OkmsKeyTypes,
OkmsServiceKeyState,
} from '@/types/okmsServiceKey.type';
import { OKMS } from '@/types/okms.type';

const useServiceKeyActionsList = (
okmsId: string,
okms: OKMS,
okmsKey?: OkmsAllServiceKeys,
isListMode?: boolean,
) => {
Expand All @@ -26,10 +27,10 @@ const useServiceKeyActionsList = (
deleteKmsServiceKey,
isPending: deleteIsPending,
} = useDeleteOkmsServiceKey({
okmsId,
okmsId: okms.id,
keyId: okmsKey?.id,
onSuccess: () => {
navigate(`/${okmsId}/${ROUTES_URLS.keys}`);
navigate(`/${okms.id}/${ROUTES_URLS.keys}`);
},
onError: () => {},
});
Expand All @@ -38,7 +39,7 @@ const useServiceKeyActionsList = (
updateKmsServiceKey,
isPending: updateIsPending,
} = useUpdateOkmsServiceKey({
okmsId,
okmsId: okms.id,
keyId: okmsKey?.id,
onSuccess: () => {
addSuccess(
Expand Down Expand Up @@ -72,9 +73,11 @@ const useServiceKeyActionsList = (
return isListMode
? navigate(`${ROUTES_URLS.serviceKeyDeactivate}/${okmsKey?.id}`)
: navigate(
`/${okmsId}/${ROUTES_URLS.keys}/${okmsKey?.id}/${ROUTES_URLS.serviceKeyDeactivate}`,
`/${okms.id}/${ROUTES_URLS.keys}/${okmsKey?.id}/${ROUTES_URLS.serviceKeyDeactivate}`,
);
},
iamActions: ['okms:apiovh:resource/serviceKey/deactivate'],
urn: okms.iam.urn,
});
}
if (
Expand All @@ -87,6 +90,8 @@ const useServiceKeyActionsList = (
color: ODS_THEME_COLOR_INTENT.primary,
disabled: updateIsPending,
onClick: () => updateKmsServiceKey({ state: OkmsServiceKeyState.active }),
iamActions: ['okms:apiovh:resource/serviceKey/activate'],
urn: okms.iam.urn,
});
}
if (
Expand All @@ -100,6 +105,8 @@ const useServiceKeyActionsList = (
disabled:
okmsKey?.state === OkmsServiceKeyState.active || deleteIsPending,
onClick: () => deleteKmsServiceKey(),
iamActions: ['okms:apiovh:resource/serviceKey/delete'],
urn: okms.iam.urn,
});
}
return items;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { useUpdateOkmsName } from '@/data/hooks/useUpdateOkmsName';
import { useKMSServiceInfos } from '@/data/hooks/useKMSServiceInfos';

const OkmsNameUpdateModal = () => {
const { t } = useTranslation('key-management-service/dashboard');
const { t: tDashboard } = useTranslation('key-management-service/dashboard');
const { t: tCredential } = useTranslation(
'key-management-service/credential',
);
const { okmsId } = useParams();
const { data: okmsServiceInfos, isLoading } = useKMSServiceInfos(okmsId);
const navigate = useNavigate();
Expand All @@ -19,8 +22,10 @@ const OkmsNameUpdateModal = () => {

return (
<UpdateNameModal
headline={t('key_management_service_dashboard_modal_title')}
inputLabel={t('key_management_service_dashboard_modal_input_label')}
headline={tDashboard('key_management_service_dashboard_modal_title')}
inputLabel={tCredential(
'key_management_service_credential_dashboard_name',
)}
defaultValue={okmsServiceInfos?.data.resource.displayName}
isLoading={isLoading || isPending}
error={error?.message}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ export default function DashboardPage() {
'key-management-service/credential',
);
const { okmsId } = useParams();
const { data: okms, isLoading: isOkmsLoading, isError: isOkmsError, error: okmsError } = useOKMSById(okmsId);
const {
data: okms,
isLoading: isOkmsLoading,
isError: isOkmsError,
error: okmsError,
} = useOKMSById(okmsId);

const {
data: okmsServiceInfos,
Expand Down Expand Up @@ -93,7 +98,7 @@ export default function DashboardPage() {
id: ROUTES_URLS.okmsUpdateName,
label: tDashboard('key_management_service_update_name'),
navigateTo: `/${okmsId}/${ROUTES_URLS.okmsUpdateName}`,
}
},
];

const headerProps: HeadersProps = {
Expand Down
Loading

0 comments on commit 74cc7c1

Please sign in to comment.