mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-15 19:16:22 +00:00
Merge remote-tracking branch 'origin/main' into misc/move-audit-logs-to-dedicated
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
export * from "./mutations";
|
||||
export * from "./queries";
|
||||
export * from "./types";
|
||||
@@ -0,0 +1,90 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { encodeBase64 } from "tweetnacl-util";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { cmekKeys } from "@app/hooks/api/cmeks/queries";
|
||||
import {
|
||||
TCmekDecrypt,
|
||||
TCmekDecryptResponse,
|
||||
TCmekEncrypt,
|
||||
TCmekEncryptResponse,
|
||||
TCreateCmek,
|
||||
TDeleteCmek,
|
||||
TUpdateCmek
|
||||
} from "@app/hooks/api/cmeks/types";
|
||||
|
||||
export const useCreateCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (payload: TCreateCmek) => {
|
||||
const { data } = await apiRequest.post("/api/v1/kms/keys", payload);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useUpdateCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, name, description, isDisabled }: TUpdateCmek) => {
|
||||
const { data } = await apiRequest.patch(`/api/v1/kms/keys/${keyId}`, {
|
||||
name,
|
||||
description,
|
||||
isDisabled
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useDeleteCmek = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId }: TDeleteCmek) => {
|
||||
const { data } = await apiRequest.delete(`/api/v1/kms/keys/${keyId}`);
|
||||
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { projectId }) => {
|
||||
queryClient.invalidateQueries(cmekKeys.getCmeksByProjectId({ projectId }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useCmekEncrypt = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, plaintext, isBase64Encoded }: TCmekEncrypt) => {
|
||||
const { data } = await apiRequest.post<TCmekEncryptResponse>(
|
||||
`/api/v1/kms/keys/${keyId}/encrypt`,
|
||||
{
|
||||
plaintext: isBase64Encoded ? plaintext : encodeBase64(Buffer.from(plaintext))
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const useCmekDecrypt = () => {
|
||||
return useMutation({
|
||||
mutationFn: async ({ keyId, ciphertext }: TCmekDecrypt) => {
|
||||
const { data } = await apiRequest.post<TCmekDecryptResponse>(
|
||||
`/api/v1/kms/keys/${keyId}/decrypt`,
|
||||
{
|
||||
ciphertext
|
||||
}
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
|
||||
|
||||
import { apiRequest } from "@app/config/request";
|
||||
import { CmekOrderBy, TListProjectCmeksDTO, TProjectCmeksList } from "@app/hooks/api/cmeks/types";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
|
||||
export const cmekKeys = {
|
||||
all: ["cmek"] as const,
|
||||
lists: () => [...cmekKeys.all, "list"] as const,
|
||||
getCmeksByProjectId: ({ projectId, ...filters }: TListProjectCmeksDTO) =>
|
||||
[...cmekKeys.lists(), projectId, filters] as const
|
||||
};
|
||||
|
||||
export const useGetCmeksByProjectId = (
|
||||
{
|
||||
projectId,
|
||||
offset = 0,
|
||||
limit = 100,
|
||||
orderBy = CmekOrderBy.Name,
|
||||
orderDirection = OrderByDirection.ASC,
|
||||
search = ""
|
||||
}: TListProjectCmeksDTO,
|
||||
options?: Omit<
|
||||
UseQueryOptions<
|
||||
TProjectCmeksList,
|
||||
unknown,
|
||||
TProjectCmeksList,
|
||||
ReturnType<typeof cmekKeys.getCmeksByProjectId>
|
||||
>,
|
||||
"queryKey" | "queryFn"
|
||||
>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: cmekKeys.getCmeksByProjectId({
|
||||
projectId,
|
||||
offset,
|
||||
limit,
|
||||
orderBy,
|
||||
orderDirection,
|
||||
search
|
||||
}),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<TProjectCmeksList>("/api/v1/kms/keys", {
|
||||
params: { projectId, offset, limit, search, orderBy, orderDirection }
|
||||
});
|
||||
|
||||
return data;
|
||||
},
|
||||
enabled: Boolean(projectId) && (options?.enabled ?? true),
|
||||
keepPreviousData: true,
|
||||
...options
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
|
||||
export type TCmek = {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
encryptionAlgorithm: EncryptionAlgorithm;
|
||||
projectId: string;
|
||||
isDisabled: boolean;
|
||||
isReserved: boolean;
|
||||
orgId: string;
|
||||
version: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
type ProjectRef = { projectId: string };
|
||||
type KeyRef = { keyId: string };
|
||||
|
||||
export type TCreateCmek = Pick<TCmek, "name" | "description" | "encryptionAlgorithm"> & ProjectRef;
|
||||
export type TUpdateCmek = KeyRef &
|
||||
Partial<Pick<TCmek, "name" | "description" | "isDisabled">> &
|
||||
ProjectRef;
|
||||
export type TDeleteCmek = KeyRef & ProjectRef;
|
||||
|
||||
export type TCmekEncrypt = KeyRef & { plaintext: string; isBase64Encoded?: boolean };
|
||||
export type TCmekDecrypt = KeyRef & { ciphertext: string };
|
||||
|
||||
export type TProjectCmeksList = {
|
||||
keys: TCmek[];
|
||||
totalCount: number;
|
||||
};
|
||||
|
||||
export type TListProjectCmeksDTO = {
|
||||
projectId: string;
|
||||
offset?: number;
|
||||
limit?: number;
|
||||
orderBy?: CmekOrderBy;
|
||||
orderDirection?: OrderByDirection;
|
||||
search?: string;
|
||||
};
|
||||
|
||||
export type TCmekEncryptResponse = {
|
||||
ciphertext: string;
|
||||
};
|
||||
|
||||
export type TCmekDecryptResponse = {
|
||||
plaintext: string;
|
||||
};
|
||||
|
||||
export enum CmekOrderBy {
|
||||
Name = "name"
|
||||
}
|
||||
|
||||
export enum EncryptionAlgorithm {
|
||||
AES_GCM_256 = "aes-256-gcm",
|
||||
AES_GCM_128 = "aes-128-gcm"
|
||||
}
|
||||
@@ -25,7 +25,8 @@ export enum DynamicSecretProviders {
|
||||
ElasticSearch = "elastic-search",
|
||||
MongoDB = "mongo-db",
|
||||
RabbitMq = "rabbit-mq",
|
||||
AzureEntraId = "azure-entra-id"
|
||||
AzureEntraId = "azure-entra-id",
|
||||
Ldap = "ldap"
|
||||
}
|
||||
|
||||
export enum SqlProviders {
|
||||
@@ -188,7 +189,20 @@ export type TDynamicSecretProvider =
|
||||
applicationId: string;
|
||||
clientSecret: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
| {
|
||||
type: DynamicSecretProviders.Ldap;
|
||||
inputs: {
|
||||
url: string;
|
||||
binddn: string;
|
||||
bindpass: string;
|
||||
ca?: string | undefined;
|
||||
creationLdif: string;
|
||||
revocationLdif: string;
|
||||
rollbackLdif?: string;
|
||||
};
|
||||
};
|
||||
;
|
||||
|
||||
export type TCreateDynamicSecretDTO = {
|
||||
projectSlug: string;
|
||||
|
||||
@@ -8,9 +8,9 @@ import { AddExternalKmsType, KmsType } from "./types";
|
||||
export const useAddExternalKms = (orgId: string) => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async ({ slug, description, provider }: AddExternalKmsType) => {
|
||||
mutationFn: async ({ name, description, provider }: AddExternalKmsType) => {
|
||||
const { data } = await apiRequest.post("/api/v1/external-kms", {
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
});
|
||||
@@ -28,14 +28,14 @@ export const useUpdateExternalKms = (orgId: string) => {
|
||||
return useMutation({
|
||||
mutationFn: async ({
|
||||
kmsId,
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
}: {
|
||||
kmsId: string;
|
||||
} & AddExternalKmsType) => {
|
||||
const { data } = await apiRequest.patch(`/api/v1/external-kms/${kmsId}`, {
|
||||
slug,
|
||||
name,
|
||||
description,
|
||||
provider
|
||||
});
|
||||
|
||||
@@ -46,7 +46,7 @@ export const useGetActiveProjectKms = (projectId: string) => {
|
||||
} = await apiRequest.get<{
|
||||
secretManagerKmsKey: {
|
||||
id: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
isExternal: string;
|
||||
};
|
||||
}>(`/api/v1/workspace/${projectId}/kms`);
|
||||
|
||||
@@ -5,7 +5,7 @@ export type Kms = {
|
||||
id: string;
|
||||
description: string;
|
||||
orgId: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
external: {
|
||||
id: string;
|
||||
status: string;
|
||||
@@ -21,7 +21,7 @@ export type KmsListEntry = {
|
||||
isDisabled: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
externalKms: {
|
||||
provider: string;
|
||||
status: string;
|
||||
@@ -88,7 +88,7 @@ export const ExternalKmsInputSchema = z.discriminatedUnion("type", [
|
||||
]);
|
||||
|
||||
export const AddExternalKmsSchema = z.object({
|
||||
slug: z
|
||||
name: z
|
||||
.string()
|
||||
.trim()
|
||||
.min(1)
|
||||
|
||||
@@ -122,6 +122,6 @@ export type TOrgIdentitiesList = {
|
||||
};
|
||||
|
||||
export enum OrgIdentityOrderBy {
|
||||
Name = "name",
|
||||
Role = "role"
|
||||
Name = "name"
|
||||
// Role = "role"
|
||||
}
|
||||
|
||||
@@ -3,13 +3,21 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@app/config/request";
|
||||
|
||||
import { secretSharingKeys } from "./queries";
|
||||
import { TCreateSharedSecretRequest, TDeleteSharedSecretRequest, TSharedSecret } from "./types";
|
||||
import {
|
||||
TCreatedSharedSecret,
|
||||
TCreateSharedSecretRequest,
|
||||
TDeleteSharedSecretRequest,
|
||||
TSharedSecret
|
||||
} from "./types";
|
||||
|
||||
export const useCreateSharedSecret = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (inputData: TCreateSharedSecretRequest) => {
|
||||
const { data } = await apiRequest.post<TSharedSecret>("/api/v1/secret-sharing", inputData);
|
||||
const { data } = await apiRequest.post<TCreatedSharedSecret>(
|
||||
"/api/v1/secret-sharing",
|
||||
inputData
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: () => queryClient.invalidateQueries(secretSharingKeys.allSharedSecrets())
|
||||
@@ -20,7 +28,7 @@ export const useCreatePublicSharedSecret = () => {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (inputData: TCreateSharedSecretRequest) => {
|
||||
const { data } = await apiRequest.post<TSharedSecret>(
|
||||
const { data } = await apiRequest.post<TCreatedSharedSecret>(
|
||||
"/api/v1/secret-sharing/public",
|
||||
inputData
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ export const secretSharingKeys = {
|
||||
allSharedSecrets: () => ["sharedSecrets"] as const,
|
||||
specificSharedSecrets: ({ offset, limit }: { offset: number; limit: number }) =>
|
||||
[...secretSharingKeys.allSharedSecrets(), { offset, limit }] as const,
|
||||
getSecretById: (arg: { id: string; hashedHex: string; password?: string }) => [
|
||||
getSecretById: (arg: { id: string; hashedHex: string | null; password?: string }) => [
|
||||
"shared-secret",
|
||||
arg
|
||||
]
|
||||
@@ -46,7 +46,7 @@ export const useGetActiveSharedSecretById = ({
|
||||
password
|
||||
}: {
|
||||
sharedSecretId: string;
|
||||
hashedHex: string;
|
||||
hashedHex: string | null;
|
||||
password?: string;
|
||||
}) => {
|
||||
return useQuery<TViewSharedSecretResponse>(
|
||||
@@ -55,7 +55,7 @@ export const useGetActiveSharedSecretById = ({
|
||||
const { data } = await apiRequest.post<TViewSharedSecretResponse>(
|
||||
`/api/v1/secret-sharing/public/${sharedSecretId}`,
|
||||
{
|
||||
hashedHex,
|
||||
...(hashedHex && { hashedHex }),
|
||||
password
|
||||
}
|
||||
);
|
||||
@@ -63,7 +63,7 @@ export const useGetActiveSharedSecretById = ({
|
||||
return data;
|
||||
},
|
||||
{
|
||||
enabled: Boolean(sharedSecretId) && Boolean(hashedHex)
|
||||
enabled: Boolean(sharedSecretId)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,13 +13,14 @@ export type TSharedSecret = {
|
||||
tag: string;
|
||||
};
|
||||
|
||||
export type TCreatedSharedSecret = {
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type TCreateSharedSecretRequest = {
|
||||
name?: string;
|
||||
password?: string;
|
||||
encryptedValue: string;
|
||||
hashedHex: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
secretValue: string;
|
||||
expiresAt: Date;
|
||||
expiresAfterViews?: number;
|
||||
accessType?: SecretSharingAccessType;
|
||||
@@ -28,6 +29,7 @@ export type TCreateSharedSecretRequest = {
|
||||
export type TViewSharedSecretResponse = {
|
||||
isPasswordProtected: boolean;
|
||||
secret: {
|
||||
secretValue?: string;
|
||||
encryptedValue: string;
|
||||
iv: string;
|
||||
tag: string;
|
||||
@@ -44,4 +46,3 @@ export enum SecretSharingAccessType {
|
||||
Anyone = "anyone",
|
||||
Organization = "organization"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export { useDebounce } from "./useDebounce";
|
||||
export { useLeaveConfirm } from "./useLeaveConfirm";
|
||||
export { usePagination } from "./usePagination";
|
||||
export { usePersistentState } from "./usePersistentState";
|
||||
export { usePopUp } from "./usePopUp";
|
||||
export { useSyntaxHighlight } from "./useSyntaxHighlight";
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
|
||||
// Ref: https://usehooks.com/useDebounce/
|
||||
export const useDebounce = <T extends unknown>(value: T, delay = 500): T => {
|
||||
export const useDebounce = <T extends unknown>(
|
||||
value: T,
|
||||
delay = 500
|
||||
): [T, Dispatch<SetStateAction<T>>] => {
|
||||
// State and setters for debounced value
|
||||
const [debouncedValue, setDebouncedValue] = useState(value);
|
||||
|
||||
@@ -22,5 +25,5 @@ export const useDebounce = <T extends unknown>(value: T, delay = 500): T => {
|
||||
[value, delay] // Only re-call effect if value or delay changes
|
||||
);
|
||||
|
||||
return debouncedValue;
|
||||
return [debouncedValue, setDebouncedValue];
|
||||
};
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { useState } from "react";
|
||||
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { useDebounce } from "@app/hooks/useDebounce";
|
||||
|
||||
export const usePagination = <T extends string>(initialOrderBy: T) => {
|
||||
const [page, setPage] = useState(1);
|
||||
const [perPage, setPerPage] = useState(20);
|
||||
const [orderDirection, setOrderDirection] = useState(OrderByDirection.ASC);
|
||||
const [orderBy, setOrderBy] = useState<T>(initialOrderBy);
|
||||
const [search, setSearch] = useState("");
|
||||
const [debouncedSearch] = useDebounce(search);
|
||||
|
||||
const offset = (page - 1) * perPage;
|
||||
|
||||
return {
|
||||
offset,
|
||||
limit: perPage,
|
||||
page,
|
||||
setPage,
|
||||
perPage,
|
||||
setPerPage,
|
||||
orderDirection,
|
||||
setOrderDirection,
|
||||
debouncedSearch,
|
||||
search,
|
||||
setSearch,
|
||||
orderBy,
|
||||
setOrderBy
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user