Skip to content

feat(kms): secrets listing page #17705

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: project/secret-management-service-b1
Choose a base branch
from

Conversation

mathieumousnier
Copy link
Contributor

Description

Ticket Reference: #MANAGER-18246

Additional Information

@mathieumousnier mathieumousnier changed the base branch from master to project/secret-management-service-b1 June 18, 2025 15:27
@github-actions github-actions bot added the has conflicts Has conflicts to resolve before merging label Jun 18, 2025
@github-actions github-actions bot removed container has conflicts Has conflicts to resolve before merging labels Jun 18, 2025
@mathieumousnier mathieumousnier marked this pull request as ready for review June 18, 2025 15:42
@mathieumousnier mathieumousnier requested a review from a team as a code owner June 18, 2025 15:42
"secret_manager": "Secret Manager",
"path": "Path",
"version": "Version",
"creation_date": "Date de création"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can replace it with creation_date from @ovh-ux/manager-common-translations

Comment on lines 6 to 11
export const getSecretList = async (okmsId: string) => {
const response = await apiClient.v2.get<Secret[]>(
`okms/resource/${okmsId}/secret`,
);
return response.data;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const getSecretList = async (okmsId: string) => {
const response = await apiClient.v2.get<Secret[]>(
`okms/resource/${okmsId}/secret`,
);
return response.data;
};
export const getSecretList = async (okmsId: string) => {
const { data } = await apiClient.v2.get<Secret[]>(
`okms/resource/${okmsId}/secret`,
);
return data;
};

for the sake of consistency, what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For me is "bonnet blanc" / "blanc bonnet".
It does the same and is colocated in the function scope.
So you prefer it like this I can do it this way.

My main concern is to avoid returning the full axios response and manage the "data" properties in the components as it is done in kms code, this makes my eyes bleed with a lot of pain :)

Comment on lines 27 to 43
it.skip('should display the secrets listing page', async () => {
await renderPage();
});

it.skip('should display the listing table with all columns', async () => {
await renderPage();

const tableHeaders = [
labels.secretManager.common.path,
labels.secretManager.common.version,
labels.secretManager.common.creation_date,
];

tableHeaders.forEach((header) => {
expect(screen.queryAllByText(header)).toHaveLength(1);
});
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it.skip('should display the secrets listing page', async () => {
await renderPage();
});
it.skip('should display the listing table with all columns', async () => {
await renderPage();
const tableHeaders = [
labels.secretManager.common.path,
labels.secretManager.common.version,
labels.secretManager.common.creation_date,
];
tableHeaders.forEach((header) => {
expect(screen.queryAllByText(header)).toHaveLength(1);
});
});
it('should display the secrets listing page', async () => {
await renderPage();
});
it('should display the listing table with all columns', async () => {
await renderPage();
const tableHeaders = [
labels.secretManager.common.path,
labels.secretManager.common.version,
labels.secretManager.common.creation_date,
];
tableHeaders.forEach((header) => {
expect(screen.queryAllByText(header)).toHaveLength(1);
});
});

forgot to unskip?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like to skip things to go faster

Comment on lines 10 to 17
export type DatagridItem = {
okmsId: string;
secret: Secret;
};

export const DatagridCellPath = (item: DatagridItem) => {
const url = SECRET_MANAGER_ROUTES_URLS.secretDashboard(
item.okmsId,
item.secret.path,
);

return <Link href={url} label={item.secret.path} useRouter />;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably better to use useParams to get the domainId instead of augmenting the secret data.

Suggested change
export type DatagridItem = {
okmsId: string;
secret: Secret;
};
export const DatagridCellPath = (item: DatagridItem) => {
const url = SECRET_MANAGER_ROUTES_URLS.secretDashboard(
item.okmsId,
item.secret.path,
);
return <Link href={url} label={item.secret.path} useRouter />;
};
export const DatagridCellPath = (item: Secret) => {
const { okmsId } = useParams();
const url = SECRET_MANAGER_ROUTES_URLS.secretDashboard(
okmsId,
item.secret.path,
);
return <Link href={url} label={item.secret.path} useRouter />;
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess your solution wins because it simplier.
But I am a bit bothered with those useParams that are implying a "context" where the component is used.
So I think I will add a .type file with the SecretListingPageParams that explicitly write the dependency.

This then opens the question about common components that would use useParams hook, and I think we just should avoid doing that.

Comment on lines 22 to 26
const items: DatagridItem[] =
secrets?.map((secret) => ({
okmsId: domainId,
secret,
})) || [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can get rid of this with useParams in the cell components

Comment on lines 48 to 56
<div className="flex flex-col gap-6">
<Datagrid
columns={columns}
items={items}
totalItems={items.length}
isLoading={isPending}
contentAlignLeft
/>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with only one child, this div with flex rules is not necessary.

Suggested change
<div className="flex flex-col gap-6">
<Datagrid
columns={columns}
items={items}
totalItems={items.length}
isLoading={isPending}
contentAlignLeft
/>
</div>
<Datagrid
columns={columns}
items={items}
totalItems={items.length}
isLoading={isPending}
contentAlignLeft
/>

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup, that was copy pasta I should have re-read

import apiClient from '@ovh-ux/manager-core-api';
import { Secret } from '@secret-manager/types/secret.type';

export const secretListQueryKey = (okmsId: string) => ['secrets/list', okmsId];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const secretListQueryKey = (okmsId: string) => ['secrets/list', okmsId];
export const secretListQueryKey = (okmsId: string) => ['secrets', 'list', okmsId];

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, I took the "/" thing from other code but it already felt weird to me.
I'll think a bit about how we should manage those keys

ref: #MANAGER-18246

Signed-off-by: Mathieu Mousnier <mathieu.mousnier.ext@ovhcloud.com>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be Listing.page.spec.tsx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be Listing.page.tsx

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be listing.type.ts

@@ -0,0 +1,3 @@
export type SecretListingPageParams = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure why this type is necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll talk about this, we'll remove it if we consider it useless.
It feels crazy to me that there is nothing to type what to expect from the router params

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants