Fix merge conflicts

This commit is contained in:
Tuan Dang
2024-03-28 12:41:34 -07:00
489 changed files with 10772 additions and 4671 deletions
+1 -4
View File
@@ -1,4 +1 @@
export {
useCreateAPIKeyV2,
useDeleteAPIKeyV2,
useUpdateAPIKeyV2} from "./queries";
export { useCreateAPIKeyV2, useDeleteAPIKeyV2, useUpdateAPIKeyV2 } from "./queries";
+12 -14
View File
@@ -8,14 +8,13 @@ import {
CreateAPIKeyDataV2DTO,
CreateServiceTokenDataV3Res,
DeleteAPIKeyDataV2DTO,
UpdateAPIKeyDataV2DTO} from "./types";
UpdateAPIKeyDataV2DTO
} from "./types";
export const useCreateAPIKeyV2 = () => {
const queryClient = useQueryClient();
return useMutation<CreateServiceTokenDataV3Res, {}, CreateAPIKeyDataV2DTO>({
mutationFn: async ({
name
}) => {
mutationFn: async ({ name }) => {
const { data } = await apiRequest.post("/api/v3/api-key", {
name
});
@@ -31,11 +30,10 @@ export const useCreateAPIKeyV2 = () => {
export const useUpdateAPIKeyV2 = () => {
const queryClient = useQueryClient();
return useMutation<APIKeyDataV2, {}, UpdateAPIKeyDataV2DTO>({
mutationFn: async ({
apiKeyDataId,
name
}) => {
const { data: { apiKeyData } } = await apiRequest.patch(`/api/v3/api-key/${apiKeyDataId}`, {
mutationFn: async ({ apiKeyDataId, name }) => {
const {
data: { apiKeyData }
} = await apiRequest.patch(`/api/v3/api-key/${apiKeyDataId}`, {
name
});
return apiKeyData;
@@ -49,14 +47,14 @@ export const useUpdateAPIKeyV2 = () => {
export const useDeleteAPIKeyV2 = () => {
const queryClient = useQueryClient();
return useMutation<APIKeyDataV2, {}, DeleteAPIKeyDataV2DTO>({
mutationFn: async ({
apiKeyDataId
}) => {
const { data: { apiKeyData } } = await apiRequest.delete(`/api/v3/api-key/${apiKeyDataId}`);
mutationFn: async ({ apiKeyDataId }) => {
const {
data: { apiKeyData }
} = await apiRequest.delete(`/api/v3/api-key/${apiKeyDataId}`);
return apiKeyData;
},
onSuccess: () => {
queryClient.invalidateQueries(userKeys.myAPIKeysV2);
}
});
};
};
+51 -51
View File
@@ -1,57 +1,57 @@
import { EventType, UserAgentType } from "./enums";
export const eventToNameMap: { [K in EventType]: string } = {
[EventType.GET_SECRETS]: "List secrets",
[EventType.GET_SECRET]: "Read secret",
[EventType.CREATE_SECRET]: "Create secret",
[EventType.UPDATE_SECRET]: "Update secret",
[EventType.DELETE_SECRET]: "Delete secret",
[EventType.GET_WORKSPACE_KEY]: "Read project key",
[EventType.AUTHORIZE_INTEGRATION]: "Authorize integration",
[EventType.UNAUTHORIZE_INTEGRATION]: "Unauthorize integration",
[EventType.CREATE_INTEGRATION]: "Create integration",
[EventType.DELETE_INTEGRATION]: "Delete integration",
[EventType.ADD_TRUSTED_IP]: "Add trusted IP",
[EventType.UPDATE_TRUSTED_IP]: "Update trusted IP",
[EventType.DELETE_TRUSTED_IP]: "Delete trusted IP",
[EventType.CREATE_SERVICE_TOKEN]: "Create service token",
[EventType.DELETE_SERVICE_TOKEN]: "Delete service token",
[EventType.CREATE_IDENTITY]: "Create identity",
[EventType.UPDATE_IDENTITY]: "Update identity",
[EventType.DELETE_IDENTITY]: "Delete identity",
[EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH]: "Login via universal auth",
[EventType.ADD_IDENTITY_UNIVERSAL_AUTH]: "Add universal auth",
[EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH]: "Update universal auth",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Create universal auth client secret",
[EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Revoke universal auth client secret",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS]: "Get universal auth client secrets",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_ENVIRONMENT]: "Create environment",
[EventType.UPDATE_ENVIRONMENT]: "Update environment",
[EventType.DELETE_ENVIRONMENT]: "Delete environment",
[EventType.ADD_WORKSPACE_MEMBER]: "Add member",
[EventType.REMOVE_WORKSPACE_MEMBER]: "Remove member",
[EventType.CREATE_FOLDER]: "Create folder",
[EventType.UPDATE_FOLDER]: "Update folder",
[EventType.DELETE_FOLDER]: "Delete folder",
[EventType.CREATE_WEBHOOK]: "Create webhook",
[EventType.UPDATE_WEBHOOK_STATUS]: "Update webhook status",
[EventType.DELETE_WEBHOOK]: "Delete webhook",
[EventType.GET_SECRET_IMPORTS]: "List secret imports",
[EventType.CREATE_SECRET_IMPORT]: "Create secret import",
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
[EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions",
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role"
[EventType.GET_SECRETS]: "List secrets",
[EventType.GET_SECRET]: "Read secret",
[EventType.CREATE_SECRET]: "Create secret",
[EventType.UPDATE_SECRET]: "Update secret",
[EventType.DELETE_SECRET]: "Delete secret",
[EventType.GET_WORKSPACE_KEY]: "Read project key",
[EventType.AUTHORIZE_INTEGRATION]: "Authorize integration",
[EventType.UNAUTHORIZE_INTEGRATION]: "Unauthorize integration",
[EventType.CREATE_INTEGRATION]: "Create integration",
[EventType.DELETE_INTEGRATION]: "Delete integration",
[EventType.ADD_TRUSTED_IP]: "Add trusted IP",
[EventType.UPDATE_TRUSTED_IP]: "Update trusted IP",
[EventType.DELETE_TRUSTED_IP]: "Delete trusted IP",
[EventType.CREATE_SERVICE_TOKEN]: "Create service token",
[EventType.DELETE_SERVICE_TOKEN]: "Delete service token",
[EventType.CREATE_IDENTITY]: "Create identity",
[EventType.UPDATE_IDENTITY]: "Update identity",
[EventType.DELETE_IDENTITY]: "Delete identity",
[EventType.LOGIN_IDENTITY_UNIVERSAL_AUTH]: "Login via universal auth",
[EventType.ADD_IDENTITY_UNIVERSAL_AUTH]: "Add universal auth",
[EventType.UPDATE_IDENTITY_UNIVERSAL_AUTH]: "Update universal auth",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Create universal auth client secret",
[EventType.REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET]: "Revoke universal auth client secret",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS]: "Get universal auth client secrets",
[EventType.GET_IDENTITY_UNIVERSAL_AUTH]: "Get universal auth",
[EventType.CREATE_ENVIRONMENT]: "Create environment",
[EventType.UPDATE_ENVIRONMENT]: "Update environment",
[EventType.DELETE_ENVIRONMENT]: "Delete environment",
[EventType.ADD_WORKSPACE_MEMBER]: "Add member",
[EventType.REMOVE_WORKSPACE_MEMBER]: "Remove member",
[EventType.CREATE_FOLDER]: "Create folder",
[EventType.UPDATE_FOLDER]: "Update folder",
[EventType.DELETE_FOLDER]: "Delete folder",
[EventType.CREATE_WEBHOOK]: "Create webhook",
[EventType.UPDATE_WEBHOOK_STATUS]: "Update webhook status",
[EventType.DELETE_WEBHOOK]: "Delete webhook",
[EventType.GET_SECRET_IMPORTS]: "List secret imports",
[EventType.CREATE_SECRET_IMPORT]: "Create secret import",
[EventType.UPDATE_SECRET_IMPORT]: "Update secret import",
[EventType.DELETE_SECRET_IMPORT]: "Delete secret import",
[EventType.UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS]: "Update denied permissions",
[EventType.UPDATE_USER_WORKSPACE_ROLE]: "Update user role"
};
export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = {
[UserAgentType.WEB]: "Web",
[UserAgentType.CLI]: "CLI",
[UserAgentType.K8_OPERATOR]: "K8s operator",
[UserAgentType.TERRAFORM]: "Terraform",
[UserAgentType.NODE_SDK]: "InfisicalNodeSDK",
[UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK",
[UserAgentType.OTHER]: "Other",
};
[UserAgentType.WEB]: "Web",
[UserAgentType.CLI]: "CLI",
[UserAgentType.K8_OPERATOR]: "K8s operator",
[UserAgentType.TERRAFORM]: "Terraform",
[UserAgentType.NODE_SDK]: "InfisicalNodeSDK",
[UserAgentType.PYTHON_SDK]: "InfisicalPythonSDK",
[UserAgentType.OTHER]: "Other"
};
+2 -2
View File
@@ -38,7 +38,7 @@ export enum EventType {
UPDATE_IDENTITY_UNIVERSAL_AUTH = "update-identity-universal-auth",
GET_IDENTITY_UNIVERSAL_AUTH = "get-identity-universal-auth",
CREATE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "create-identity-universal-auth-client-secret",
REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret",
REVOKE_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRET = "revoke-identity-universal-auth-client-secret",
GET_IDENTITY_UNIVERSAL_AUTH_CLIENT_SECRETS = "get-identity-universal-auth-client-secret",
CREATE_ENVIRONMENT = "create-environment",
UPDATE_ENVIRONMENT = "update-environment",
@@ -57,4 +57,4 @@ export enum EventType {
DELETE_SECRET_IMPORT = "delete-secret-import",
UPDATE_USER_WORKSPACE_ROLE = "update-user-workspace-role",
UPDATE_USER_WORKSPACE_DENIED_PERMISSIONS = "update-user-workspace-denied-permissions"
}
}
+1 -1
View File
@@ -1 +1 @@
export * from "./queries";
export * from "./queries";
+18 -18
View File
@@ -4,12 +4,12 @@ export type GetAuthTokenAPI = {
export type SendMfaTokenDTO = {
email: string;
}
};
export type VerifyMfaTokenDTO = {
email: string;
mfaCode: string;
}
};
export type VerifyMfaTokenRes = {
encryptionVersion: number;
@@ -21,24 +21,24 @@ export type VerifyMfaTokenRes = {
encryptedPrivateKey: string;
iv: string;
tag: string;
}
};
export type Login1DTO = {
email: string;
clientPublicKey: string;
providerAuthToken?: string;
}
};
export type Login2DTO = {
email: string;
clientProof: string;
providerAuthToken?: string;
}
};
export type Login1Res = {
serverPublicKey: string;
salt: string;
}
};
export type Login2Res = {
mfaEnabled: boolean;
@@ -51,26 +51,26 @@ export type Login2Res = {
encryptedPrivateKey?: string;
iv?: string;
tag?: string;
}
};
export type LoginLDAPDTO = {
organizationSlug: string;
username: string;
password: string;
}
};
export type LoginLDAPRes = {
nextUrl: string;
}
};
export type SRP1DTO = {
clientPublicKey: string;
}
};
export type SRPR1Res = {
serverPublicKey: string;
salt: string;
}
};
export type CompleteAccountDTO = {
email: string;
@@ -85,19 +85,19 @@ export type CompleteAccountDTO = {
encryptedPrivateKeyTag: string;
salt: string;
verifier: string;
}
};
export type CompleteAccountSignupDTO = CompleteAccountDTO & {
providerAuthToken?: string;
attributionSource?: string;
organizationName: string;
}
};
export type VerifySignupInviteDTO = {
email: string;
code: string;
organizationId: string;
}
};
export type ChangePasswordDTO = {
clientProof: string;
@@ -109,7 +109,7 @@ export type ChangePasswordDTO = {
encryptedPrivateKeyTag: string;
salt: string;
verifier: string;
}
};
export type ResetPasswordDTO = {
protectedKey: string;
@@ -121,7 +121,7 @@ export type ResetPasswordDTO = {
salt: string;
verifier: string;
verificationToken: string;
}
};
export type IssueBackupPrivateKeyDTO = {
encryptedPrivateKey: string;
@@ -130,8 +130,8 @@ export type IssueBackupPrivateKeyDTO = {
salt: string;
verifier: string;
clientProof: string;
}
};
export type GetBackupEncryptedPrivateKeyDTO = {
verificationToken: string;
}
};
+3 -1
View File
@@ -12,7 +12,9 @@ export const useGetWorkspaceBot = (workspaceId: string) =>
useQuery({
queryKey: queryKeys.getBot(workspaceId),
queryFn: async () => {
const { data: { bot } } = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`);
const {
data: { bot }
} = await apiRequest.get<{ bot: TBot }>(`/api/v1/bot/${workspaceId}`);
return bot;
},
enabled: Boolean(workspaceId)
@@ -0,0 +1,6 @@
export { useCreateDynamicSecret, useDeleteDynamicSecret, useUpdateDynamicSecret } from "./mutation";
export {
useGetDynamicSecretDetails,
useGetDynamicSecrets,
useGetDynamicSecretsOfAllEnv
} from "./queries";
@@ -0,0 +1,62 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { dynamicSecretKeys } from "./queries";
import {
TCreateDynamicSecretDTO,
TDeleteDynamicSecretDTO,
TDynamicSecret,
TUpdateDynamicSecretDTO
} from "./types";
export const useCreateDynamicSecret = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TCreateDynamicSecretDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.post<{ dynamicSecret: TDynamicSecret }>(
"/api/v1/dynamic-secrets",
dto
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};
export const useUpdateDynamicSecret = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TUpdateDynamicSecretDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.patch<{ dynamicSecret: TDynamicSecret }>(
`/api/v1/dynamic-secrets/${dto.name}`,
dto
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};
export const useDeleteDynamicSecret = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TDeleteDynamicSecretDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.delete<{ dynamicSecret: TDynamicSecret }>(
`/api/v1/dynamic-secrets/${dto.name}`,
{ data: dto }
);
return data.dynamicSecret;
},
onSuccess: (_, { path, environmentSlug, projectSlug }) => {
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environmentSlug }));
}
});
};
@@ -0,0 +1,126 @@
import { useCallback, useMemo } from "react";
import { useQueries, useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import {
TDetailsDynamicSecretDTO,
TDynamicSecret,
TGetDynamicSecretsByEnvsDTO,
TListDynamicSecretDTO
} from "./types";
export const dynamicSecretKeys = {
list: ({
projectSlug,
environmentSlug,
path
}: 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,
environmentSlug,
path
}: TListDynamicSecretDTO) => {
return useQuery({
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,
environmentSlug,
path
}
}
);
return data.dynamicSecrets;
}
});
};
export const useGetDynamicSecretDetails = ({
projectSlug,
environmentSlug,
path,
name
}: TDetailsDynamicSecretDTO) => {
return useQuery({
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/${name}`, {
params: {
projectSlug,
environmentSlug,
path
}
});
return data.dynamicSecret;
}
});
};
export const useGetDynamicSecretsOfAllEnv = ({
path,
projectSlug,
environmentSlugs
}: TGetDynamicSecretsByEnvsDTO) => {
const dynamicSecrets = useQueries({
queries: environmentSlugs.map((environment) => ({
queryKey: dynamicSecretKeys.list({ path, environmentSlug: environment, projectSlug }),
enabled: Boolean(projectSlug && environment && path),
queryFn: async () => {
const { data } = await apiRequest.get<{ dynamicSecrets: TDynamicSecret[] }>(
"/api/v1/dynamic-secrets",
{
params: {
projectSlug,
environmentSlug: environment,
path
}
}
);
return data.dynamicSecrets;
}
}))
});
const dynamicSecretNames = useMemo(() => {
const names = new Set<string>();
dynamicSecrets?.forEach(({ data }) => {
data?.forEach(({ name }) => {
names.add(name);
});
});
return [...names];
}, [(dynamicSecrets || []).map((dynamicSecret) => dynamicSecret.data)]);
const isDynamicSecretPresentInEnv = useCallback(
(name: string, env: string) => {
const selectedEnvIndex = environmentSlugs.indexOf(env);
if (selectedEnvIndex !== -1) {
return Boolean(
dynamicSecrets?.[selectedEnvIndex]?.data?.find(
({ name: dynamicSecretName }) => dynamicSecretName === name
)
);
}
return false;
},
[(dynamicSecrets || []).map((el) => el.data)]
);
return { dynamicSecrets, isDynamicSecretPresentInEnv, dynamicSecretNames };
};
@@ -0,0 +1,90 @@
export enum DynamicSecretStatus {
Deleting = "Revocation in process",
FailedDeletion = "Failed to delete"
}
// TODO(akhilmhdh): When we switch to monorepo all the server api ts will be in a shared repo
export type TDynamicSecret = {
id: string;
name: string;
type: DynamicSecretProviders;
createdAt: string;
updatedAt: string;
defaultTTL: string;
status?: DynamicSecretStatus;
statusDetails?: string;
maxTTL: string;
};
export enum DynamicSecretProviders {
SqlDatabase = "sql-database"
}
export enum SqlProviders {
Postgres = "postgres"
}
export type TDynamicSecretProvider = {
type: DynamicSecretProviders;
inputs: {
client: SqlProviders;
host: string;
port: number;
database: string;
username: string;
password: string;
creationStatement: string;
revocationStatement: string;
renewStatement: string;
ca?: string | undefined;
};
};
export type TCreateDynamicSecretDTO = {
projectSlug: string;
provider: TDynamicSecretProvider;
defaultTTL: string;
maxTTL?: string;
path: string;
environmentSlug: string;
name: string;
};
export type TUpdateDynamicSecretDTO = {
name: string;
projectSlug: string;
path: string;
environmentSlug: string;
data: {
newName?: string;
defaultTTL?: string;
maxTTL?: string | null;
inputs?: unknown;
};
};
export type TListDynamicSecretDTO = {
projectSlug: string;
path: string;
environmentSlug: string;
};
export type TDeleteDynamicSecretDTO = {
projectSlug: string;
path: string;
environmentSlug: string;
name: string;
isForced?: boolean;
};
export type TDetailsDynamicSecretDTO = {
projectSlug: string;
path: string;
environmentSlug: string;
name: string;
};
export type TGetDynamicSecretsByEnvsDTO = {
projectSlug: string;
path: string;
environmentSlugs: string[];
};
@@ -0,0 +1,6 @@
export {
useCreateDynamicSecretLease,
useRenewDynamicSecretLease,
useRevokeDynamicSecretLease
} from "./mutation";
export { useGetDynamicSecretLeases } from "./queries";
@@ -0,0 +1,72 @@
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { dynamicSecretLeaseKeys } from "./queries";
import {
TCreateDynamicSecretLeaseDTO,
TDynamicSecretLease,
TRenewDynamicSecretLeaseDTO,
TRevokeDynamicSecretLeaseDTO
} from "./types";
export const useCreateDynamicSecretLease = () => {
const queryClient = useQueryClient();
return useMutation<
{ lease: TDynamicSecretLease; data: unknown },
{},
TCreateDynamicSecretLeaseDTO
>({
mutationFn: async (dto) => {
const { data } = await apiRequest.post<{ lease: TDynamicSecretLease; data: unknown }>(
"/api/v1/dynamic-secrets/leases",
dto
);
return data;
},
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});
};
export const useRenewDynamicSecretLease = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TRenewDynamicSecretLeaseDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.post<{ lease: TDynamicSecretLease }>(
`/api/v1/dynamic-secrets/leases/${dto.leaseId}/renew`,
dto
);
return data.lease;
},
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});
};
export const useRevokeDynamicSecretLease = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, TRevokeDynamicSecretLeaseDTO>({
mutationFn: async (dto) => {
const { data } = await apiRequest.delete<{ lease: TDynamicSecretLease }>(
`/api/v1/dynamic-secrets/leases/${dto.leaseId}`,
{ data: dto }
);
return data.lease;
},
onSuccess: (_, { path, environmentSlug, projectSlug, dynamicSecretName }) => {
queryClient.invalidateQueries(
dynamicSecretLeaseKeys.list({ path, projectSlug, environmentSlug, dynamicSecretName })
);
}
});
};
@@ -0,0 +1,39 @@
import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { TDynamicSecretLease, TListDynamicSecretLeaseDTO } from "./types";
export const dynamicSecretLeaseKeys = {
list: ({ projectSlug, environmentSlug, path, dynamicSecretName }: TListDynamicSecretLeaseDTO) =>
[{ projectSlug, environmentSlug, path, dynamicSecretName }, "dynamic-secret-leases"] as const
};
export const useGetDynamicSecretLeases = ({
projectSlug,
environmentSlug,
path,
dynamicSecretName,
enabled = true
}: TListDynamicSecretLeaseDTO) => {
return useQuery({
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/${dynamicSecretName}/leases`,
{
params: {
projectSlug,
environmentSlug,
path
}
}
);
return data.leases;
}
});
};
@@ -0,0 +1,49 @@
export enum DynamicSecretLeaseStatus {
FailedDeletion = "Failed to delete"
}
export type TDynamicSecretLease = {
id: string;
version: number;
expireAt: string;
dynamicSecretId: string;
status?: DynamicSecretLeaseStatus;
statusDetails?: string;
createdAt: string;
updatedAt: string;
};
export type TCreateDynamicSecretLeaseDTO = {
dynamicSecretName: string;
projectSlug: string;
ttl?: string;
path: string;
environmentSlug: string;
};
export type TRenewDynamicSecretLeaseDTO = {
leaseId: string;
dynamicSecretName: string;
ttl?: string;
projectSlug: string;
path: string;
environmentSlug: string;
};
export type TListDynamicSecretLeaseDTO = {
dynamicSecretName: string;
projectSlug: string;
path: string;
environmentSlug: string;
enabled?: boolean;
};
export type TRevokeDynamicSecretLeaseDTO = {
leaseId: string;
dynamicSecretName: string;
projectSlug: string;
path: string;
environmentSlug: string;
isForced?: boolean;
};
@@ -1,5 +1,5 @@
import { IdentityAuthMethod } from "./enums";
export const identityAuthToNameMap: { [I in IdentityAuthMethod]: string } = {
[IdentityAuthMethod.UNIVERSAL_AUTH]: "Universal Auth"
};
[IdentityAuthMethod.UNIVERSAL_AUTH]: "Universal Auth"
};
+9 -11
View File
@@ -1,14 +1,12 @@
export { identityAuthToNameMap } from "./constants";
export { IdentityAuthMethod } from "./enums";
export {
useAddIdentityUniversalAuth,
useCreateIdentity,
useCreateIdentityUniversalAuthClientSecret,
useDeleteIdentity,
useRevokeIdentityUniversalAuthClientSecret,
useUpdateIdentity,
useUpdateIdentityUniversalAuth} from "./mutations";
export {
useGetIdentityUniversalAuth,
useGetIdentityUniversalAuthClientSecrets
} from "./queries";
useAddIdentityUniversalAuth,
useCreateIdentity,
useCreateIdentityUniversalAuthClientSecret,
useDeleteIdentity,
useRevokeIdentityUniversalAuthClientSecret,
useUpdateIdentity,
useUpdateIdentityUniversalAuth
} from "./mutations";
export { useGetIdentityUniversalAuth, useGetIdentityUniversalAuthClientSecrets } from "./queries";
+142 -135
View File
@@ -4,161 +4,168 @@ import { apiRequest } from "@app/config/request";
import { organizationKeys } from "../organization/queries";
import { identitiesKeys } from "./queries";
import {
AddIdentityUniversalAuthDTO,
ClientSecretData,
CreateIdentityDTO,
CreateIdentityUniversalAuthClientSecretDTO,
CreateIdentityUniversalAuthClientSecretRes,
DeleteIdentityDTO,
DeleteIdentityUniversalAuthClientSecretDTO,
Identity,
IdentityUniversalAuth,
UpdateIdentityDTO,
UpdateIdentityUniversalAuthDTO} from "./types";
import {
AddIdentityUniversalAuthDTO,
ClientSecretData,
CreateIdentityDTO,
CreateIdentityUniversalAuthClientSecretDTO,
CreateIdentityUniversalAuthClientSecretRes,
DeleteIdentityDTO,
DeleteIdentityUniversalAuthClientSecretDTO,
Identity,
IdentityUniversalAuth,
UpdateIdentityDTO,
UpdateIdentityUniversalAuthDTO
} from "./types";
export const useCreateIdentity = () => {
const queryClient = useQueryClient();
return useMutation<Identity, {}, CreateIdentityDTO>({
mutationFn: async (body) => {
const { data: { identity } } = await apiRequest.post("/api/v1/identities/", body);
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
const queryClient = useQueryClient();
return useMutation<Identity, {}, CreateIdentityDTO>({
mutationFn: async (body) => {
const {
data: { identity }
} = await apiRequest.post("/api/v1/identities/", body);
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
};
export const useUpdateIdentity = () => {
const queryClient = useQueryClient();
return useMutation<Identity, {}, UpdateIdentityDTO>({
mutationFn: async ({
identityId,
name,
role
}) => {
const { data: { identity } } = await apiRequest.patch(`/api/v1/identities/${identityId}`, {
name,
role
});
const queryClient = useQueryClient();
return useMutation<Identity, {}, UpdateIdentityDTO>({
mutationFn: async ({ identityId, name, role }) => {
const {
data: { identity }
} = await apiRequest.patch(`/api/v1/identities/${identityId}`, {
name,
role
});
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
}
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
};
export const useDeleteIdentity = () => {
const queryClient = useQueryClient();
return useMutation<Identity, {}, DeleteIdentityDTO>({
mutationFn: async ({
identityId,
}) => {
const { data: { identity } } = await apiRequest.delete(`/api/v1/identities/${identityId}`);
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
const queryClient = useQueryClient();
return useMutation<Identity, {}, DeleteIdentityDTO>({
mutationFn: async ({ identityId }) => {
const {
data: { identity }
} = await apiRequest.delete(`/api/v1/identities/${identityId}`);
return identity;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
};
// TODO: move these to /auth
export const useAddIdentityUniversalAuth = () => {
const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, AddIdentityUniversalAuthDTO>({
mutationFn: async ({
identityId,
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
}) => {
const { data: { identityUniversalAuth } } = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}`,
{
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
}
);
return identityUniversalAuth;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, AddIdentityUniversalAuthDTO>({
mutationFn: async ({
identityId,
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps
}) => {
const {
data: { identityUniversalAuth }
} = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}`, {
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps
});
return identityUniversalAuth;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
};
export const useUpdateIdentityUniversalAuth = () => {
const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, UpdateIdentityUniversalAuthDTO>({
mutationFn: async ({
identityId,
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
}) => {
const { data: { identityUniversalAuth } } = await apiRequest.patch(`/api/v1/auth/universal-auth/identities/${identityId}`,
{
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps,
}
);
return identityUniversalAuth;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
const queryClient = useQueryClient();
return useMutation<IdentityUniversalAuth, {}, UpdateIdentityUniversalAuthDTO>({
mutationFn: async ({
identityId,
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps
}) => {
const {
data: { identityUniversalAuth }
} = await apiRequest.patch(`/api/v1/auth/universal-auth/identities/${identityId}`, {
clientSecretTrustedIps,
accessTokenTTL,
accessTokenMaxTTL,
accessTokenNumUsesLimit,
accessTokenTrustedIps
});
return identityUniversalAuth;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(organizationKeys.getOrgIdentityMemberships(organizationId));
}
});
};
export const useCreateIdentityUniversalAuthClientSecret = () => {
const queryClient = useQueryClient();
return useMutation<CreateIdentityUniversalAuthClientSecretRes, {}, CreateIdentityUniversalAuthClientSecretDTO>({
mutationFn: async ({
identityId,
description,
ttl,
numUsesLimit
}) => {
const { data } = await apiRequest.post(`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`, {
description,
ttl,
numUsesLimit
});
return data;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId));
const queryClient = useQueryClient();
return useMutation<
CreateIdentityUniversalAuthClientSecretRes,
{},
CreateIdentityUniversalAuthClientSecretDTO
>({
mutationFn: async ({ identityId, description, ttl, numUsesLimit }) => {
const { data } = await apiRequest.post(
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`,
{
description,
ttl,
numUsesLimit
}
});
);
return data;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(
identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId)
);
}
});
};
export const useRevokeIdentityUniversalAuthClientSecret = () => {
const queryClient = useQueryClient();
return useMutation<ClientSecretData, {}, DeleteIdentityUniversalAuthClientSecretDTO>({
mutationFn: async ({
identityId,
clientSecretId
}) => {
const { data: { clientSecretData } } = await apiRequest.post<{ clientSecretData: ClientSecretData }>(`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets/${clientSecretId}/revoke`);
return clientSecretData;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId));
}
});
};
const queryClient = useQueryClient();
return useMutation<ClientSecretData, {}, DeleteIdentityUniversalAuthClientSecretDTO>({
mutationFn: async ({ identityId, clientSecretId }) => {
const {
data: { clientSecretData }
} = await apiRequest.post<{ clientSecretData: ClientSecretData }>(
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets/${clientSecretId}/revoke`
);
return clientSecretData;
},
onSuccess: (_, { identityId }) => {
queryClient.invalidateQueries(
identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId)
);
}
});
};
+34 -28
View File
@@ -2,39 +2,45 @@ import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { ClientSecretData , IdentityUniversalAuth } from "./types";
import { ClientSecretData, IdentityUniversalAuth } from "./types";
export const identitiesKeys = {
getIdentityUniversalAuth: (identityId: string) => [{ identityId }, "identity-universal-auth"] as const,
getIdentityUniversalAuthClientSecrets: (identityId: string) => [{ identityId }, "identity-universal-auth-client-secrets"] as const
}
getIdentityUniversalAuth: (identityId: string) =>
[{ identityId }, "identity-universal-auth"] as const,
getIdentityUniversalAuthClientSecrets: (identityId: string) =>
[{ identityId }, "identity-universal-auth-client-secrets"] as const
};
export const useGetIdentityUniversalAuth = (identityId: string) => {
return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuth(identityId),
queryFn: async () => {
if (identityId === "") throw new Error("Identity ID is required");
return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuth(identityId),
queryFn: async () => {
if (identityId === "") throw new Error("Identity ID is required");
const { data: { identityUniversalAuth } } = await apiRequest.get<{ identityUniversalAuth: IdentityUniversalAuth }>(
`/api/v1/auth/universal-auth/identities/${identityId}`
);
return identityUniversalAuth;
}
});
}
const {
data: { identityUniversalAuth }
} = await apiRequest.get<{ identityUniversalAuth: IdentityUniversalAuth }>(
`/api/v1/auth/universal-auth/identities/${identityId}`
);
return identityUniversalAuth;
}
});
};
export const useGetIdentityUniversalAuthClientSecrets = (identityId: string) => {
return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId),
queryFn: async () => {
if (identityId === "") return [];
return useQuery({
queryKey: identitiesKeys.getIdentityUniversalAuthClientSecrets(identityId),
queryFn: async () => {
if (identityId === "") return [];
const { data: { clientSecretData } } = await apiRequest.get<{ clientSecretData: ClientSecretData[] }>(
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`
);
return clientSecretData;
}
});
}
const {
data: { clientSecretData }
} = await apiRequest.get<{ clientSecretData: ClientSecretData[] }>(
`/api/v1/auth/universal-auth/identities/${identityId}/client-secrets`
);
return clientSecretData;
}
});
};
+4 -2
View File
@@ -1,9 +1,11 @@
export * from "./admin"
export * from "./admin";
export * from "./apiKeys";
export * from "./auditLogs";
export * from "./auth";
export * from "./bots";
export * from "./groups";
export * from "./dynamicSecret";
export * from "./dynamicSecretLease";
export * from "./identities";
export * from "./incidentContacts";
export * from "./integrationAuth";
@@ -28,4 +30,4 @@ export * from "./tags";
export * from "./trustedIps";
export * from "./users";
export * from "./webhooks";
export * from "./workspace";
export * from "./workspace";
@@ -15,4 +15,4 @@ export {
useGetIntegrationAuthTeams,
useGetIntegrationAuthVercelBranches,
useSaveIntegrationAccessToken
} from "./queries";
} from "./queries";
@@ -68,8 +68,8 @@ const integrationAuthKeys = {
environmentId: string;
scope: "job" | "application" | "container";
}) => [{ integrationAuthId, environmentId, scope }, "integrationAuthQoveryScopes"] as const,
getIntegrationAuthHerokuPipelines: ({ integrationAuthId }: { integrationAuthId: string; }) =>
[{ integrationAuthId}, "integrationAuthHerokuPipelines"] as const,
getIntegrationAuthHerokuPipelines: ({ integrationAuthId }: { integrationAuthId: string }) =>
[{ integrationAuthId }, "integrationAuthHerokuPipelines"] as const,
getIntegrationAuthRailwayEnvironments: ({
integrationAuthId,
appId
@@ -322,8 +322,10 @@ const fetchIntegrationAuthQoveryScopes = async ({
return undefined;
};
const fetchIntegrationAuthHerokuPipelines = async ({ integrationAuthId }: {
integrationAuthId: string;
const fetchIntegrationAuthHerokuPipelines = async ({
integrationAuthId
}: {
integrationAuthId: string;
}) => {
const {
data: { pipelines }
@@ -1,5 +1 @@
export {
useCreateIntegration,
useDeleteIntegration,
useGetCloudIntegrations
} from "./queries";
export { useCreateIntegration, useDeleteIntegration, useGetCloudIntegrations } from "./queries";
@@ -63,9 +63,11 @@ export const useCreateIntegration = () => {
secretSuffix?: string;
initialSyncBehavior?: string;
shouldAutoRedeploy?: boolean;
}
};
}) => {
const { data: { integration } } = await apiRequest.post("/api/v1/integration", {
const {
data: { integration }
} = await apiRequest.post("/api/v1/integration", {
integrationAuthId,
isActive,
app,
@@ -101,4 +103,4 @@ export const useDeleteIntegration = () => {
queryClient.invalidateQueries(workspaceKeys.getWorkspaceAuthorization(workspaceId));
}
});
};
};
+1 -5
View File
@@ -1,5 +1 @@
export {
useCreateLDAPConfig,
useGetLDAPConfig,
useUpdateLDAPConfig
} from "./queries";
export { useCreateLDAPConfig, useGetLDAPConfig, useUpdateLDAPConfig } from "./queries";
+43 -51
View File
@@ -3,27 +3,42 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
const ldapConfigKeys = {
getLDAPConfig: (orgId: string) => [{ orgId }, "organization-ldap"] as const,
}
getLDAPConfig: (orgId: string) => [{ orgId }, "organization-ldap"] as const
};
export const useGetLDAPConfig = (organizationId: string) => {
return useQuery({
queryKey: ldapConfigKeys.getLDAPConfig(organizationId),
queryFn: async () => {
const { data } = await apiRequest.get(
`/api/v1/ldap/config?organizationId=${organizationId}`
);
const { data } = await apiRequest.get(`/api/v1/ldap/config?organizationId=${organizationId}`);
return data;
},
enabled: true
});
}
};
export const useCreateLDAPConfig = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive: boolean;
url: string;
bindDN: string;
bindPass: string;
searchBase: string;
caCert?: string;
}) => {
const { data } = await apiRequest.post("/api/v1/ldap/config", {
organizationId,
isActive,
url,
@@ -31,28 +46,8 @@ export const useCreateLDAPConfig = () => {
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive: boolean;
url: string;
bindDN: string;
bindPass: string;
searchBase: string;
caCert?: string;
}) => {
const { data } = await apiRequest.post(
"/api/v1/ldap/config",
{
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}
);
});
return data;
},
onSuccess(_, dto) {
@@ -65,6 +60,23 @@ export const useUpdateLDAPConfig = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive?: boolean;
url?: string;
bindDN?: string;
bindPass?: string;
searchBase?: string;
caCert?: string;
}) => {
const { data } = await apiRequest.patch("/api/v1/ldap/config", {
organizationId,
isActive,
url,
@@ -72,32 +84,12 @@ export const useUpdateLDAPConfig = () => {
bindPass,
searchBase,
caCert
}: {
organizationId: string;
isActive?: boolean;
url?: string;
bindDN?: string;
bindPass?: string;
searchBase?: string;
caCert?: string;
}) => {
const { data } = await apiRequest.patch(
"/api/v1/ldap/config",
{
organizationId,
isActive,
url,
bindDN,
bindPass,
searchBase,
caCert
}
);
});
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(ldapConfigKeys.getLDAPConfig(dto.organizationId));
}
});
};
};
+22 -21
View File
@@ -1,22 +1,23 @@
export {
useAddOrgPmtMethod,
useAddOrgTaxId,
useCreateCustomerPortalSession,
useCreateOrg,
useDeleteOrgById,
useDeleteOrgPmtMethod,
useDeleteOrgTaxId,
useGetIdentityMembershipOrgs,
useGetOrganizationGroups,
useGetOrganizations,
useGetOrgBillingDetails,
useGetOrgInvoices,
useGetOrgLicenses,
useGetOrgPlanBillingInfo,
useGetOrgPlansTable,
useGetOrgPlanTable,
useGetOrgPmtMethods,
useGetOrgTaxIds,
useGetOrgTrialUrl,
useUpdateOrg,
useUpdateOrgBillingDetails} from "./queries";
useAddOrgPmtMethod,
useAddOrgTaxId,
useCreateCustomerPortalSession,
useCreateOrg,
useDeleteOrgById,
useDeleteOrgPmtMethod,
useDeleteOrgTaxId,
useGetIdentityMembershipOrgs,
useGetOrganizationGroups,
useGetOrganizations,
useGetOrgBillingDetails,
useGetOrgInvoices,
useGetOrgLicenses,
useGetOrgPlanBillingInfo,
useGetOrgPlansTable,
useGetOrgPlanTable,
useGetOrgPmtMethods,
useGetOrgTaxIds,
useGetOrgTrialUrl,
useUpdateOrg,
useUpdateOrgBillingDetails
} from "./queries";
+2 -5
View File
@@ -1,5 +1,2 @@
export {
useCreateScimToken,
useDeleteScimToken
} from "./mutations";
export { useGetScimTokens } from "./queries";
export { useCreateScimToken, useDeleteScimToken } from "./mutations";
export { useGetScimTokens } from "./queries";
+27 -35
View File
@@ -3,43 +3,35 @@ import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { scimKeys } from "./queries";
import {
CreateScimTokenDTO,
CreateScimTokenRes,
DeleteScimTokenDTO
} from "./types";
import { CreateScimTokenDTO, CreateScimTokenRes, DeleteScimTokenDTO } from "./types";
export const useCreateScimToken = () => {
const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, CreateScimTokenDTO>({
mutationFn: async ({
organizationId,
description,
ttlDays
}) => {
const { data } = await apiRequest.post("/api/v1/scim/scim-tokens", {
organizationId,
description,
ttlDays
});
return data;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
}
});
const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, CreateScimTokenDTO>({
mutationFn: async ({ organizationId, description, ttlDays }) => {
const { data } = await apiRequest.post("/api/v1/scim/scim-tokens", {
organizationId,
description,
ttlDays
});
return data;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
}
});
};
export const useDeleteScimToken = () => {
const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, DeleteScimTokenDTO>({
mutationFn: async ({ scimTokenId }) => {
const { data } = await apiRequest.delete(`/api/v1/scim/scim-tokens/${scimTokenId}`);
return data;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
}
});
};
const queryClient = useQueryClient();
return useMutation<CreateScimTokenRes, {}, DeleteScimTokenDTO>({
mutationFn: async ({ scimTokenId }) => {
const { data } = await apiRequest.delete(`/api/v1/scim/scim-tokens/${scimTokenId}`);
return data;
},
onSuccess: (_, { organizationId }) => {
queryClient.invalidateQueries(scimKeys.getScimTokens(organizationId));
}
});
};
+19 -15
View File
@@ -5,21 +5,25 @@ import { apiRequest } from "@app/config/request";
import { ScimTokenData } from "./types";
export const scimKeys = {
getScimTokens: (orgId: string) => [{ orgId }, "organization-scim-token"] as const,
getScimTokens: (orgId: string) => [{ orgId }, "organization-scim-token"] as const
};
export const useGetScimTokens = (organizationId: string) => {
return useQuery({
queryKey: scimKeys.getScimTokens(organizationId),
queryFn: async () => {
if (organizationId === "") {
return undefined;
}
const { data: { scimTokens } } = await apiRequest.get<{ scimTokens: ScimTokenData[] }>(`/api/v1/scim/scim-tokens?organizationId=${organizationId}`);
return scimTokens;
},
enabled: true
});
};
return useQuery({
queryKey: scimKeys.getScimTokens(organizationId),
queryFn: async () => {
if (organizationId === "") {
return undefined;
}
const {
data: { scimTokens }
} = await apiRequest.get<{ scimTokens: ScimTokenData[] }>(
`/api/v1/scim/scim-tokens?organizationId=${organizationId}`
);
return scimTokens;
},
enabled: true
});
};
+16 -16
View File
@@ -1,24 +1,24 @@
export type ScimTokenData = {
id: string;
ttlDays: number;
description: string;
tokenSuffix: string;
orgId: string;
createdAt: string;
updatedAt: string;
id: string;
ttlDays: number;
description: string;
tokenSuffix: string;
orgId: string;
createdAt: string;
updatedAt: string;
};
export type CreateScimTokenDTO = {
organizationId: string;
description?: string;
ttlDays?: number;
}
organizationId: string;
description?: string;
ttlDays?: number;
};
export type DeleteScimTokenDTO = {
organizationId: string;
scimTokenId: string;
}
organizationId: string;
scimTokenId: string;
};
export type CreateScimTokenRes = {
scimToken: string;
}
scimToken: string;
};
@@ -1,2 +1,7 @@
export { useCreateSecretImport, useDeleteSecretImport, useUpdateSecretImport } from "./mutation";
export { useGetImportedSecrets, useGetSecretImports } from "./queries";
export {
useGetImportedFoldersByEnv,
useGetImportedSecretsAllEnvs,
useGetImportedSecretsSingleEnv,
useGetSecretImports
} from "./queries";
@@ -1,5 +1,5 @@
import { useCallback } from "react";
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { useQueries, useQuery, UseQueryOptions } from "@tanstack/react-query";
import {
decryptAssymmetric,
@@ -7,7 +7,15 @@ import {
} from "@app/components/utilities/cryptography/crypto";
import { apiRequest } from "@app/config/request";
import { TGetImportedSecrets, TGetSecretImports, TImportedSecrets, TSecretImport } from "./types";
import {
TGetImportedFoldersByEnvDTO,
TGetImportedSecrets,
TGetSecretImports,
TGetSecretImportsAllEnvs,
TImportedSecrets,
TSecretImport,
TuseGetImportedFoldersByEnv
} from "./types";
export const secretImportKeys = {
getProjectSecretImports: ({ environment, projectId, path }: TGetSecretImports) =>
@@ -17,7 +25,11 @@ export const secretImportKeys = {
projectId,
path
}: Omit<TGetImportedSecrets, "decryptFileKey">) =>
[{ environment, path, projectId }, "secrets-import-sec"] as const
[{ environment, path, projectId }, "secrets-import-sec"] as const,
getImportedFoldersByEnv: ({ environment, projectId, path }: TGetImportedFoldersByEnvDTO) =>
[{ environment, projectId, path }, "imported-folders"] as const,
getImportedFoldersAllEnvs: ({ projectId, path, environment }: TGetImportedFoldersByEnvDTO) =>
[{ projectId, path, environment }, "imported-folders-all-envs"] as const
};
const fetchSecretImport = async ({ projectId, environment, path = "/" }: TGetSecretImports) => {
@@ -75,7 +87,25 @@ const fetchImportedSecrets = async (
return data.secrets;
};
export const useGetImportedSecrets = ({
const fetchImportedFolders = async ({
projectId,
environment,
path
}: TGetImportedFoldersByEnvDTO) => {
const { data } = await apiRequest.get<{ secretImports: TSecretImport[] }>(
"/api/v1/secret-imports",
{
params: {
workspaceId: projectId,
environment,
path
}
}
);
return data.secretImports;
};
export const useGetImportedSecretsSingleEnv = ({
environment,
decryptFileKey,
path,
@@ -159,3 +189,138 @@ export const useGetImportedSecrets = ({
[decryptFileKey]
)
});
export const useGetImportedSecretsAllEnvs = ({
projectId,
environments,
path = "/",
decryptFileKey
}: TGetSecretImportsAllEnvs) => {
const secretImports = useQueries({
queries: environments.map((env) => ({
queryKey: secretImportKeys.getImportedFoldersAllEnvs({
environment: env,
projectId,
path
}),
queryFn: () => fetchImportedSecrets(projectId, env, path).catch(() => []),
enabled: Boolean(projectId) && Boolean(env),
// eslint-disable-next-line react-hooks/rules-of-hooks
select: useCallback(
(data: TImportedSecrets[]) => {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY") as string;
const latestKey = decryptFileKey;
const key = decryptAssymmetric({
ciphertext: latestKey.encryptedKey,
nonce: latestKey.nonce,
publicKey: latestKey.sender.publicKey,
privateKey: PRIVATE_KEY
});
return data.map((el) => ({
environment: el.environment,
secretPath: el.secretPath,
environmentInfo: el.environmentInfo,
folderId: el.folderId,
secrets: el.secrets.map((encSecret) => {
const secretKey = decryptSymmetric({
ciphertext: encSecret.secretKeyCiphertext,
iv: encSecret.secretKeyIV,
tag: encSecret.secretKeyTag,
key
});
const secretValue = decryptSymmetric({
ciphertext: encSecret.secretValueCiphertext,
iv: encSecret.secretValueIV,
tag: encSecret.secretValueTag,
key
});
const secretComment = decryptSymmetric({
ciphertext: encSecret.secretCommentCiphertext,
iv: encSecret.secretCommentIV,
tag: encSecret.secretCommentTag,
key
});
return {
id: encSecret.id,
env: encSecret.environment,
key: secretKey,
value: secretValue,
tags: encSecret.tags,
comment: secretComment,
createdAt: encSecret.createdAt,
updatedAt: encSecret.updatedAt,
version: encSecret.version
};
})
}));
},
[decryptFileKey]
)
}))
});
const isImportedSecretPresentInEnv = useCallback(
(secPath: string, envSlug: string, secretName: string) => {
const selectedEnvIndex = environments.indexOf(envSlug);
if (selectedEnvIndex !== -1) {
const isPresent = secretImports?.[selectedEnvIndex]?.data?.find(
({ secretPath, secrets }) =>
secretPath === secPath && secrets.some((s) => s.key === secretName)
);
return Boolean(isPresent);
}
return false;
},
[(secretImports || []).map((response) => response.data)]
);
return { secretImports, isImportedSecretPresentInEnv };
};
export const useGetImportedFoldersByEnv = ({
projectId,
environments,
path = "/"
}: TuseGetImportedFoldersByEnv) => {
const queryParams = new URLSearchParams(window.location.search);
const currentPath = path;
const importedFolders = useQueries({
queries: environments.map((env) => ({
queryKey: secretImportKeys.getImportedFoldersByEnv({
projectId,
environment: env,
path: currentPath
}),
queryFn: async () => fetchImportedFolders({ projectId, environment: env, path: currentPath }),
enabled: Boolean(projectId) && Boolean(env)
}))
});
const isImportedFolderPresentInEnv = useCallback(
(name: string, env: string) => {
const selectedEnvIndex = environments.indexOf(env);
if (selectedEnvIndex !== -1) {
const currentlyBrowsingPath = queryParams.get("secretPath") || "";
const isPresent = importedFolders?.[selectedEnvIndex]?.data?.find(
({ importPath }) => importPath === `${currentlyBrowsingPath}/${name}`
);
return Boolean(isPresent);
}
return false;
},
[(importedFolders || []).map((response) => response.data)]
);
return { importedFolders, isImportedFolderPresentInEnv };
};
@@ -12,6 +12,12 @@ export type TSecretImport = {
updatedAt: string;
};
export type TGetImportedFoldersByEnvDTO = {
projectId: string;
environment: string;
path?: string;
};
export type TImportedSecrets = {
environment: string;
environmentInfo: WorkspaceEnv;
@@ -26,6 +32,13 @@ export type TGetSecretImports = {
path?: string;
};
export type TGetSecretImportsAllEnvs = {
projectId: string;
decryptFileKey: UserWsKeyPair;
path?: string;
environments: string[];
};
export type TGetImportedSecrets = {
projectId: string;
environment: string;
@@ -33,6 +46,12 @@ export type TGetImportedSecrets = {
decryptFileKey: UserWsKeyPair;
};
export type TuseGetImportedFoldersByEnv = {
environments: string[];
projectId: string;
path?: string;
};
export type TCreateSecretImportDTO = {
projectId: string;
environment: string;
@@ -1 +1 @@
export { useFetchServerStatus } from "./queries"
export { useFetchServerStatus } from "./queries";
@@ -1,4 +1,4 @@
import {useQuery } from "@tanstack/react-query";
import { useQuery } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
@@ -10,10 +10,10 @@ const serverStatusKeys = {
};
const fetchServerStatus = async () => {
const {data} = await apiRequest.get<ServerStatus>("/api/status");
const { data } = await apiRequest.get<ServerStatus>("/api/status");
return data;
};
export const useFetchServerStatus= () => {
export const useFetchServerStatus = () => {
return useQuery({ queryKey: serverStatusKeys.serverStatus, queryFn: fetchServerStatus });
}
};
@@ -2,6 +2,6 @@ export type ServerStatus = {
date: string;
message: string;
emailConfigured: boolean;
secretScanningConfigured: boolean
redisConfigured: boolean
secretScanningConfigured: boolean;
redisConfigured: boolean;
};
@@ -1,4 +1,4 @@
export enum Permission {
READ = "read",
WRITE = "write"
}
READ = "read",
WRITE = "write"
}
@@ -1,5 +1 @@
export {
useCreateServiceToken,
useDeleteServiceToken,
useGetUserWsServiceTokens,
} from "./queries";
export { useCreateServiceToken, useDeleteServiceToken, useGetUserWsServiceTokens } from "./queries";
+1 -5
View File
@@ -1,5 +1 @@
export {
useCreateSSOConfig,
useGetSSOConfig,
useUpdateSSOConfig
} from "./queries";
export { useCreateSSOConfig, useGetSSOConfig, useUpdateSSOConfig } from "./queries";
+1 -1
View File
@@ -87,7 +87,7 @@ export const useUpdateSSOConfig = () => {
if (isActive === false) {
queryClient.invalidateQueries(organizationKeys.getUserOrganizations);
}
queryClient.invalidateQueries(ssoConfigKeys.getSSOConfig(organizationId));
}
});
@@ -3,6 +3,7 @@ export type SubscriptionPlan = {
membersUsed: number;
memberLimit: number;
auditLogs: boolean;
dynamicSecret: boolean;
auditLogsRetentionDays: number;
customAlerts: boolean;
customRateLimits: boolean;
@@ -22,14 +23,14 @@ export type SubscriptionPlan = {
ldap: boolean;
groups: 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;
};
+5 -4
View File
@@ -1,5 +1,6 @@
export {
useAddTrustedIp,
useDeleteTrustedIp,
useGetTrustedIps,
useUpdateTrustedIp} from "./queries";
useAddTrustedIp,
useDeleteTrustedIp,
useGetTrustedIps,
useUpdateTrustedIp
} from "./queries";
+85 -88
View File
@@ -2,107 +2,104 @@ import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import {
TrustedIp
} from "./types";
import { TrustedIp } from "./types";
const trustedIps = {
getTrustedIps: (workspaceId: string) => [{ workspaceId }, "trusted-ips"] as const
}
getTrustedIps: (workspaceId: string) => [{ workspaceId }, "trusted-ips"] as const
};
export const useGetTrustedIps = (workspaceId: string) => {
return useQuery({
queryKey: trustedIps.getTrustedIps(workspaceId),
queryFn: async () => {
const { data } = await apiRequest.get<{ trustedIps: TrustedIp[] }>(`/api/v1/workspace/${workspaceId}/trusted-ips`);
return useQuery({
queryKey: trustedIps.getTrustedIps(workspaceId),
queryFn: async () => {
const { data } = await apiRequest.get<{ trustedIps: TrustedIp[] }>(
`/api/v1/workspace/${workspaceId}/trusted-ips`
);
return data.trustedIps;
}
});
}
return data.trustedIps;
}
});
};
export const useAddTrustedIp = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
ipAddress,
comment,
isActive
}: {
workspaceId: string;
ipAddress: string;
comment?: string;
isActive: boolean;
}) => {
const { data } = await apiRequest.post(
`/api/v1/workspace/${workspaceId}/trusted-ips`,
{
ipAddress,
...(comment ? { comment } : {}),
isActive
}
);
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
ipAddress,
comment,
isActive
}: {
workspaceId: string;
ipAddress: string;
comment?: string;
isActive: boolean;
}) => {
const { data } = await apiRequest.post(`/api/v1/workspace/${workspaceId}/trusted-ips`, {
ipAddress,
...(comment ? { comment } : {}),
isActive
});
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
};
export const useUpdateTrustedIp = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
trustedIpId,
ipAddress,
comment,
isActive
}: {
workspaceId: string;
trustedIpId: string;
ipAddress: string;
comment?: string;
isActive: boolean;
}) => {
const { data } = await apiRequest.patch(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`,
{
ipAddress,
...(comment ? { comment } : {}),
isActive
}
);
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
trustedIpId,
ipAddress,
comment,
isActive
}: {
workspaceId: string;
trustedIpId: string;
ipAddress: string;
comment?: string;
isActive: boolean;
}) => {
const { data } = await apiRequest.patch(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`,
{
ipAddress,
...(comment ? { comment } : {}),
isActive
}
});
);
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
};
export const useDeleteTrustedIp = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
trustedIpId,
}: {
workspaceId: string;
trustedIpId: string;
}) => {
const { data } = await apiRequest.delete(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`
);
const queryClient = useQueryClient();
return useMutation({
mutationFn: async ({
workspaceId,
trustedIpId
}: {
workspaceId: string;
trustedIpId: string;
}) => {
const { data } = await apiRequest.delete(
`/api/v1/workspace/${workspaceId}/trusted-ips/${trustedIpId}`
);
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
};
return data;
},
onSuccess(_, dto) {
queryClient.invalidateQueries(trustedIps.getTrustedIps(dto.workspaceId));
}
});
};
+22
View File
@@ -1,3 +1,5 @@
import { ZodIssue } from "zod";
export type { GetAuthTokenAPI } from "./auth/types";
export type { IncidentContact } from "./incidentContacts/types";
export type { IntegrationAuth } from "./integrationAuth/types";
@@ -36,3 +38,23 @@ export type {
WorkspaceEnv,
WorkspaceTag
} from "./workspace/types";
export enum ApiErrorTypes {
ValidationError = "ValidationFailure",
BadRequestError = "BadRequest",
UnauthorizedError = "UnauthorizedError",
ForbiddenError = "PermissionDenied"
}
export type TApiErrors =
| {
error: ApiErrorTypes.ValidationError;
message: ZodIssue[];
statusCode: 403;
}
| { error: ApiErrorTypes.ForbiddenError; message: string; statusCode: 401 }
| {
statusCode: 400;
message: string;
error: ApiErrorTypes.BadRequestError;
};
+1
View File
@@ -3,4 +3,5 @@ export { useLeaveConfirm } from "./useLeaveConfirm";
export { usePersistentState } from "./usePersistentState";
export { usePopUp } from "./usePopUp";
export { useSyntaxHighlight } from "./useSyntaxHighlight";
export { useTimedReset } from "./useTimedReset";
export { useToggle } from "./useToggle";
+25
View File
@@ -0,0 +1,25 @@
import { Dispatch, SetStateAction, useEffect, useState } from "react";
type Props<T extends unknown> = {
initialState: T;
delay?: number;
};
// this hook is used when you need to reset the state to previous one after a particular time
// usecase#1: To make copy to copied and back to copy in clipboard operation
export const useTimedReset = <T extends string | number | boolean>({
delay = 2000,
initialState
}: Props<T>): [T, boolean, Dispatch<SetStateAction<T>>] => {
const [state, setState] = useState<T>(initialState);
useEffect(() => {
let timer: NodeJS.Timeout;
if (state !== initialState) {
timer = setTimeout(() => setState(initialState), delay);
}
return () => clearTimeout(timer);
}, [state]);
// state, isChaning, setState
return [state, state !== initialState, setState];
};