feat(ui): updated api changes made

This commit is contained in:
Akhil Mohan
2024-03-26 14:10:25 +05:30
parent a7d2ec80c6
commit 8a7774f9ac
15 changed files with 120 additions and 116 deletions

View File

@@ -21,8 +21,8 @@ export const useCreateDynamicSecret = () => {
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environment, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};
@@ -33,13 +33,13 @@ export const useUpdateDynamicSecret = () => {
return useMutation<{}, {}, TUpdateDynamicSecretDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.patch<{ dynamicSecret: TDynamicSecret }>(
`/api/v1/dynamic-secrets/${dto.slug}`,
`/api/v1/dynamic-secrets/${dto.name}`,
dto
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environment, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};
@@ -50,13 +50,13 @@ export const useDeleteDynamicSecret = () => {
return useMutation<{}, {}, TDeleteDynamicSecretDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.delete<{ dynamicSecret: TDynamicSecret }>(
`/api/v1/dynamic-secrets/${dto.slug}`,
`/api/v1/dynamic-secrets/${dto.name}`,
{ data: dto }
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environment, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};

View File

@@ -7,25 +7,25 @@ import { TDetailsDynamicSecretDTO, TDynamicSecret, TListDynamicSecretDTO } from
export const dynamicSecretKeys = {
list: ({
projectSlug,
environment,
environmentSlug,
path
}: Pick<TListDynamicSecretDTO, "path" | "environment" | "projectSlug">) =>
[{ projectSlug, environment, path }, "dynamic-secrets"] as const,
details: ({ path, environment, projectSlug, slug }: TDetailsDynamicSecretDTO) =>
[{ projectSlug, path, environment, slug }, "dynamic-secret-details"] as const
}: Pick<TListDynamicSecretDTO, "path" | "environmentSlug" | "projectSlug">) =>
[{ projectSlug, environmentSlug, path }, "dynamic-secrets"] as const,
details: ({ path, environmentSlug, projectSlug, name }: TDetailsDynamicSecretDTO) =>
[{ projectSlug, path, environmentSlug, name }, "dynamic-secret-details"] as const
};
export const useGetDynamicSecrets = ({ projectSlug, environment, path }: TListDynamicSecretDTO) => {
export const useGetDynamicSecrets = ({ projectSlug, environmentSlug, path }: TListDynamicSecretDTO) => {
return useQuery({
queryKey: dynamicSecretKeys.list({ path, environment, projectSlug }),
enabled: Boolean(projectSlug && environment && path),
queryKey: dynamicSecretKeys.list({ path, environmentSlug, projectSlug }),
enabled: Boolean(projectSlug && environmentSlug && path),
queryFn: async () => {
const { data } = await apiRequest.get<{ dynamicSecrets: TDynamicSecret[] }>(
"/api/v1/dynamic-secrets",
{
params: {
projectSlug,
environment,
environmentSlug,
path
}
}
@@ -38,20 +38,20 @@ export const useGetDynamicSecrets = ({ projectSlug, environment, path }: TListDy
export const useGetDynamicSecretDetails = ({
projectSlug,
environment,
environmentSlug,
path,
slug
name
}: TDetailsDynamicSecretDTO) => {
return useQuery({
queryKey: dynamicSecretKeys.details({ path, environment, projectSlug, slug }),
enabled: Boolean(projectSlug && environment && path && slug),
queryKey: dynamicSecretKeys.details({ path, environmentSlug, projectSlug, name }),
enabled: Boolean(projectSlug && environmentSlug && path && name),
queryFn: async () => {
const { data } = await apiRequest.get<{
dynamicSecret: TDynamicSecret & { inputs: unknown };
}>(`/api/v1/dynamic-secrets/${slug}`, {
}>(`/api/v1/dynamic-secrets/${name}`, {
params: {
projectSlug,
environment,
environmentSlug,
path
}
});

View File

@@ -5,7 +5,7 @@ export enum DynamicSecretStatus {
// TODO(akhilmhdh): When we switch to monorepo all the server api ts will be in a shared repo
export type TDynamicSecret = {
id: string;
slug: string;
name: string;
type: DynamicSecretProviders;
createdAt: string;
updatedAt: string;
@@ -45,17 +45,17 @@ export type TCreateDynamicSecretDTO = {
defaultTTL: string;
maxTTL?: string;
path: string;
environment: string;
slug: string;
environmentSlug: string;
name: string;
};
export type TUpdateDynamicSecretDTO = {
slug: string;
name: string;
projectSlug: string;
path: string;
environment: string;
environmentSlug: string;
data: {
newSlug?: string;
newName?: string;
defaultTTL?: string;
maxTTL?: string | null;
inputs?: unknown;
@@ -65,20 +65,20 @@ export type TUpdateDynamicSecretDTO = {
export type TListDynamicSecretDTO = {
projectSlug: string;
path: string;
environment: string;
environmentSlug: string;
};
export type TDeleteDynamicSecretDTO = {
projectSlug: string;
path: string;
environment: string;
slug: string;
environmentSlug: string;
name: string;
isForced?: boolean;
};
export type TDetailsDynamicSecretDTO = {
projectSlug: string;
path: string;
environment: string;
slug: string;
environmentSlug: string;
name: string;
};

View File

@@ -25,9 +25,9 @@ export const useCreateDynamicSecretLease = () => {
);
return data;
},
onSuccess: (_, { path, environment, projectSlug, slug }) => {
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});
@@ -44,9 +44,9 @@ export const useRenewDynamicSecretLease = () => {
);
return data.lease;
},
onSuccess: (_, { path, environment, projectSlug, slug }) => {
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});
@@ -63,9 +63,9 @@ export const useRevokeDynamicSecretLease = () => {
);
return data.lease;
},
onSuccess: (_, { path, environment, projectSlug, slug }) => {
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});

View File

@@ -5,27 +5,27 @@ import { apiRequest } from "@app/config/request";
import { TDynamicSecretLease, TListDynamicSecretLeaseDTO } from "./types";
export const dynamicSecretLeaseKeys = {
list: ({ projectSlug, environment, path, slug }: TListDynamicSecretLeaseDTO) =>
[{ projectSlug, environment, path, slug }, "dynamic-secret-leases"] as const
list: ({ projectSlug, environmentSlug, path, dynamicSecretName }: TListDynamicSecretLeaseDTO) =>
[{ projectSlug, environmentSlug, path, dynamicSecretName }, "dynamic-secret-leases"] as const
};
export const useGetDynamicSecretLeases = ({
projectSlug,
environment,
environmentSlug,
path,
slug,
dynamicSecretName,
enabled = true
}: TListDynamicSecretLeaseDTO) => {
return useQuery({
queryKey: dynamicSecretLeaseKeys.list({ path, environment, projectSlug, slug }),
enabled: Boolean(projectSlug && environment && path && slug && enabled),
queryKey: dynamicSecretLeaseKeys.list({ path, environmentSlug, projectSlug, dynamicSecretName }),
enabled: Boolean(projectSlug && environmentSlug && path && dynamicSecretName && enabled),
queryFn: async () => {
const { data } = await apiRequest.get<{ leases: TDynamicSecretLease[] }>(
`/api/v1/dynamic-secrets/${slug}/leases`,
`/api/v1/dynamic-secrets/${dynamicSecretName}/leases`,
{
params: {
projectSlug,
environment,
environmentSlug,
path
}
}

View File

@@ -14,35 +14,35 @@ export type TDynamicSecretLease = {
};
export type TCreateDynamicSecretLeaseDTO = {
slug: string;
dynamicSecretName: string;
projectSlug: string;
ttl?: string;
path: string;
environment: string;
environmentSlug: string;
};
export type TRenewDynamicSecretLeaseDTO = {
leaseId: string;
slug: string;
dynamicSecretName: string;
ttl?: string;
projectSlug: string;
path: string;
environment: string;
environmentSlug: string;
};
export type TListDynamicSecretLeaseDTO = {
slug: string;
dynamicSecretName: string;
projectSlug: string;
path: string;
environment: string;
environmentSlug: string;
enabled?: boolean;
};
export type TRevokeDynamicSecretLeaseDTO = {
leaseId: string;
slug: string;
dynamicSecretName: string;
projectSlug: string;
path: string;
environment: string;
environmentSlug: string;
isForced?: boolean;
};

View File

@@ -3,6 +3,7 @@ export type SubscriptionPlan = {
membersUsed: number;
memberLimit: number;
auditLogs: boolean;
dynamicSecret: boolean;
auditLogsRetentionDays: number;
customAlerts: boolean;
customRateLimits: boolean;
@@ -21,14 +22,14 @@ export type SubscriptionPlan = {
scim: boolean;
ldap: boolean;
status:
| "incomplete"
| "incomplete_expired"
| "trialing"
| "active"
| "past_due"
| "canceled"
| "unpaid"
| null;
| "incomplete"
| "incomplete_expired"
| "trialing"
| "active"
| "past_due"
| "canceled"
| "unpaid"
| null;
trial_end: number | null;
has_used_trial: boolean;
};

View File

@@ -141,7 +141,7 @@ export const SecretMainPage = () => {
const { data: dynamicSecrets, isLoading: isDynamicSecretLoading } = useGetDynamicSecrets({
projectSlug,
environment,
environmentSlug: environment,
path: secretPath
});

View File

@@ -54,7 +54,9 @@ const formSchema = z.object({
if (valMs > 24 * 60 * 60 * 1000)
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
}),
slug: z.string().toLowerCase()
name: z
.string()
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
});
type TForm = z.infer<typeof formSchema>;
@@ -92,18 +94,18 @@ export const SqlDatabaseInputForm = ({
const { createNotification } = useNotificationContext();
const createDynamicSecret = useCreateDynamicSecret();
const handleCreateDynamicSecret = async ({ slug, maxTTL, provider, defaultTTL }: TForm) => {
const handleCreateDynamicSecret = async ({ name, maxTTL, provider, defaultTTL }: TForm) => {
// wait till previous request is finished
if (createDynamicSecret.isLoading) return;
try {
await createDynamicSecret.mutateAsync({
provider: { type: DynamicSecretProviders.SqlDatabase, inputs: provider },
maxTTL,
slug,
name,
path: secretPath,
defaultTTL,
projectSlug,
environment
environmentSlug: environment
});
onCompleted();
} catch (err) {
@@ -122,7 +124,7 @@ export const SqlDatabaseInputForm = ({
<Controller
control={control}
defaultValue=""
name="slug"
name="name"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Name"
@@ -168,9 +170,11 @@ export const SqlDatabaseInputForm = ({
</div>
</div>
<div>
<div className="mb-4 border-b border-mineshaft-500 pb-2 text-mineshaft-200 pl-1 mt-4 font-medium">Configuration</div>
<div className="mb-4 mt-4 border-b border-mineshaft-500 pb-2 pl-1 font-medium text-mineshaft-200">
Configuration
</div>
<div className="flex flex-col">
<div className="text-sm text-mineshaft-400 pl-1 pb-0.5">Service</div>
<div className="pl-1 pb-0.5 text-sm text-mineshaft-400">Service</div>
<Controller
control={control}
name="provider.client"
@@ -279,11 +283,7 @@ export const SqlDatabaseInputForm = ({
</FormControl>
)}
/>
<Accordion
type="single"
collapsible
className="w-full bg-mineshaft-700 mb-2"
>
<Accordion type="single" collapsible className="mb-2 w-full bg-mineshaft-700">
<AccordionItem value="advance-statements">
<AccordionTrigger>Modify SQL Statements</AccordionTrigger>
<AccordionContent>

View File

@@ -77,7 +77,7 @@ type TForm = z.infer<typeof formSchema>;
type Props = {
onClose: () => void;
slug: string;
dynamicSecretName: string;
provider: DynamicSecretProviders;
projectSlug: string;
environment: string;
@@ -87,7 +87,7 @@ type Props = {
export const CreateDynamicSecretLease = ({
onClose,
projectSlug,
slug,
dynamicSecretName,
provider,
secretPath,
environment
@@ -110,11 +110,11 @@ export const CreateDynamicSecretLease = ({
if (createDynamicSecretLease.isLoading) return;
try {
await createDynamicSecretLease.mutateAsync({
environment,
environmentSlug: environment,
projectSlug,
path: secretPath,
ttl,
slug
dynamicSecretName
});
createNotification({
type: "success",

View File

@@ -34,7 +34,7 @@ import { DynamicSecretLeaseStatus } from "@app/hooks/api/dynamicSecretLease/type
import { RenewDynamicSecretLease } from "./RenewDynamicSecretLease";
type Props = {
slug: string;
dynamicSecretName: string;
projectSlug: string;
environment: string;
secretPath: string;
@@ -44,7 +44,7 @@ type Props = {
export const DynamicSecretLease = ({
projectSlug,
slug,
dynamicSecretName,
environment,
secretPath,
onClickNewLease,
@@ -56,9 +56,9 @@ export const DynamicSecretLease = ({
] as const);
const { data: leases, isLoading: isLeaseLoading } = useGetDynamicSecretLeases({
projectSlug,
environment,
environmentSlug: environment,
path: secretPath,
slug
dynamicSecretName
});
const { createNotification } = useNotificationContext();
@@ -71,10 +71,10 @@ export const DynamicSecretLease = ({
isForced?: boolean;
};
await deleteDynamicSecretLease.mutateAsync({
environment,
environmentSlug: environment,
projectSlug,
path: secretPath,
slug,
dynamicSecretName,
leaseId,
isForced
});
@@ -226,7 +226,7 @@ export const DynamicSecretLease = ({
onClose={() => handlePopUpClose("renewSecret")}
projectSlug={projectSlug}
leaseId={(popUp.renewSecret?.data as { leaseId: string })?.leaseId}
slug={slug}
dynamicSecretName={dynamicSecretName}
secretPath={secretPath}
environment={environment}
/>

View File

@@ -64,14 +64,14 @@ export const DynamicSecretListView = ({
const handleDynamicSecretDelete = async () => {
try {
const { slug, isForced } = popUp.deleteDynamicSecret.data as TDynamicSecret & {
const { name, isForced } = popUp.deleteDynamicSecret.data as TDynamicSecret & {
isForced?: boolean;
};
await deleteDynamicSecret.mutateAsync({
environment,
environmentSlug: environment,
projectSlug,
path: secretPath,
slug,
name,
isForced
});
handlePopUpClose("deleteDynamicSecret");
@@ -93,8 +93,8 @@ export const DynamicSecretListView = ({
{dynamicSecrets
.sort((a, b) =>
sortDir === SortDir.ASC
? a.slug.toLowerCase().localeCompare(b.slug.toLowerCase())
: b.slug.toLowerCase().localeCompare(a.slug.toLowerCase())
? a.name.toLowerCase().localeCompare(b.name.toLowerCase())
: b.name.toLowerCase().localeCompare(a.name.toLowerCase())
)
.map((secret) => {
const isRevocking = secret.status === DynamicSecretStatus.Deleting;
@@ -124,11 +124,11 @@ export const DynamicSecretListView = ({
<FontAwesomeIcon icon={faFingerprint} />
</div>
<div
className="flex flex-grow items-center px-4 py-3 uppercase"
className="flex flex-grow items-center px-4 py-3"
role="button"
tabIndex={0}
>
{secret.slug}{" "}
{secret.name}
<Tag className="ml-4 py-0 px-2 text-xs normal-case">
{formatProviderName(secret.type)}
</Tag>
@@ -234,7 +234,7 @@ export const DynamicSecretListView = ({
onClose={() => handlePopUpClose("dynamicSecretLeases")}
projectSlug={projectSlug}
key={secret.id}
slug={secret.slug}
dynamicSecretName={secret.name}
secretPath={secretPath}
environment={environment}
/>
@@ -253,7 +253,7 @@ export const DynamicSecretListView = ({
}
onClose={() => handlePopUpClose("createDynamicSecretLease")}
projectSlug={projectSlug}
slug={(popUp.createDynamicSecretLease?.data as { slug: string })?.slug}
dynamicSecretName={(popUp.createDynamicSecretLease?.data as { name: string })?.name}
secretPath={secretPath}
environment={environment}
/>
@@ -267,7 +267,7 @@ export const DynamicSecretListView = ({
<EditDynamicSecretForm
onClose={() => handlePopUpClose("updateDynamicSecret")}
projectSlug={projectSlug}
slug={(popUp.updateDynamicSecret?.data as TDynamicSecret)?.slug}
dynamicSecretName={(popUp.updateDynamicSecret?.data as TDynamicSecret)?.name}
secretPath={secretPath}
environment={environment}
/>
@@ -275,7 +275,7 @@ export const DynamicSecretListView = ({
</Modal>
<DeleteActionModal
isOpen={popUp.deleteDynamicSecret.isOpen}
deleteKey={(popUp.deleteDynamicSecret?.data as TDynamicSecret)?.slug}
deleteKey={(popUp.deleteDynamicSecret?.data as TDynamicSecret)?.name}
title={
(popUp.deleteDynamicSecret?.data as { isForced?: boolean })?.isForced
? "Do you want to force delete this dynamic secret?"

View File

@@ -8,14 +8,14 @@ import { EditDynamicSecretSqlProviderForm } from "./EditDynamicSecretSqlProvider
type Props = {
onClose: () => void;
slug: string;
dynamicSecretName: string;
projectSlug: string;
environment: string;
secretPath: string;
};
export const EditDynamicSecretForm = ({
slug,
dynamicSecretName,
environment,
projectSlug,
onClose,
@@ -24,8 +24,8 @@ export const EditDynamicSecretForm = ({
const { data: dynamicSecretDetails, isLoading: isDynamicSecretLoading } =
useGetDynamicSecretDetails({
projectSlug,
environment,
slug,
environmentSlug: environment,
name: dynamicSecretName,
path: secretPath
});

View File

@@ -57,7 +57,10 @@ const formSchema = z.object({
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
})
.nullable(),
newSlug: z.string().toLowerCase().optional()
newName: z
.string()
.refine((val) => val.toLowerCase() === val, "Must be lowercase")
.optional()
});
type TForm = z.infer<typeof formSchema>;
@@ -85,7 +88,7 @@ export const EditDynamicSecretSqlProviderForm = ({
values: {
defaultTTL: dynamicSecret.defaultTTL,
maxTTL: dynamicSecret.maxTTL,
newSlug: dynamicSecret.slug,
newName: dynamicSecret.name,
inputs: {
...(dynamicSecret.inputs as TForm["inputs"])
}
@@ -94,31 +97,31 @@ export const EditDynamicSecretSqlProviderForm = ({
const { createNotification } = useNotificationContext();
const updateDynamicSecret = useUpdateDynamicSecret();
const handleUpdateDynamicSecret = async ({ inputs, maxTTL, defaultTTL, newSlug }: TForm) => {
const handleUpdateDynamicSecret = async ({ inputs, maxTTL, defaultTTL, newName }: TForm) => {
// wait till previous request is finished
if (updateDynamicSecret.isLoading) return;
try {
await updateDynamicSecret.mutateAsync({
slug: dynamicSecret.slug,
name: dynamicSecret.name,
path: secretPath,
projectSlug,
environment,
environmentSlug: environment,
data: {
maxTTL: maxTTL || undefined,
defaultTTL,
inputs,
newSlug: newSlug === dynamicSecret.slug ? undefined : newSlug
newName: newName === dynamicSecret.name ? undefined : newName
}
});
onClose();
createNotification({
type: "success",
text: "Successfully updated dynamic secret"
text: "Successfully update dynamic secret"
});
} catch (err) {
createNotification({
type: "error",
text: "Failed to create dynamic secret"
text: "Failed to update dynamic secret"
});
}
};
@@ -130,7 +133,7 @@ export const EditDynamicSecretSqlProviderForm = ({
<div className="flex-grow">
<Controller
control={control}
name="newSlug"
name="newName"
render={({ field, fieldState: { error } }) => (
<FormControl
label="Secret Name"

View File

@@ -24,7 +24,7 @@ type TForm = z.infer<typeof formSchema>;
type Props = {
onClose: () => void;
leaseId: string;
slug: string;
dynamicSecretName: string;
projectSlug: string;
environment: string;
secretPath: string;
@@ -33,7 +33,7 @@ type Props = {
export const RenewDynamicSecretLease = ({
onClose,
projectSlug,
slug,
dynamicSecretName,
leaseId,
secretPath,
environment
@@ -56,11 +56,11 @@ export const RenewDynamicSecretLease = ({
if (renewDynamicSecretLease.isLoading) return;
try {
await renewDynamicSecretLease.mutateAsync({
environment,
environmentSlug: environment,
projectSlug,
path: secretPath,
ttl,
slug,
dynamicSecretName,
leaseId
});
onClose();