mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat: changed the whole api from projectid to slug
This commit is contained in:
2
backend/src/@types/fastify.d.ts
vendored
2
backend/src/@types/fastify.d.ts
vendored
@@ -64,7 +64,7 @@ declare module "fastify" {
|
||||
authMethod: ActorAuthMethod;
|
||||
type: ActorType;
|
||||
id: string;
|
||||
orgId?: string;
|
||||
orgId: string;
|
||||
};
|
||||
// passport data
|
||||
passportUser: {
|
||||
|
||||
@@ -13,7 +13,7 @@ export type TProjectPermission = {
|
||||
actorId: string;
|
||||
projectId: string;
|
||||
actorAuthMethod: ActorAuthMethod;
|
||||
actorOrgId: string | undefined;
|
||||
actorOrgId: string;
|
||||
};
|
||||
|
||||
export type RequiredKeys<T> = {
|
||||
|
||||
@@ -16,7 +16,7 @@ export type TAuthMode =
|
||||
userId: string;
|
||||
tokenVersionId: string; // the session id of token used
|
||||
user: TUsers;
|
||||
orgId?: string;
|
||||
orgId: string;
|
||||
authMethod: AuthMethod;
|
||||
}
|
||||
| {
|
||||
@@ -119,7 +119,7 @@ export const injectIdentity = fp(async (server: FastifyZodProvider) => {
|
||||
userId: user.id,
|
||||
tokenVersionId,
|
||||
actor,
|
||||
orgId,
|
||||
orgId: orgId as string,
|
||||
authMethod: token.authMethod
|
||||
};
|
||||
break;
|
||||
|
||||
@@ -566,6 +566,7 @@ export const registerRoutes = async (
|
||||
dynamicSecretDAL
|
||||
});
|
||||
const dynamicSecretService = dynamicSecretServiceFactory({
|
||||
projectDAL,
|
||||
dynamicSecretQueueService,
|
||||
dynamicSecretDAL,
|
||||
dynamicSecretLeaseDAL,
|
||||
@@ -574,6 +575,7 @@ export const registerRoutes = async (
|
||||
permissionService
|
||||
});
|
||||
const dynamicSecretLeaseService = dynamicSecretLeaseServiceFactory({
|
||||
projectDAL,
|
||||
permissionService,
|
||||
dynamicSecretQueueService,
|
||||
dynamicSecretDAL,
|
||||
|
||||
@@ -7,14 +7,16 @@ import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
import { AuthMode } from "@app/services/auth/auth-type";
|
||||
|
||||
import { SanitizedDynamicSecretSchema } from "../sanitizedSchemas";
|
||||
|
||||
export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvider) => {
|
||||
server.route({
|
||||
url: "/",
|
||||
method: "POST",
|
||||
schema: {
|
||||
body: z.object({
|
||||
slug: z.string(),
|
||||
projectId: z.string(),
|
||||
slug: z.string().min(1),
|
||||
projectSlug: z.string().min(1),
|
||||
ttl: z
|
||||
.string()
|
||||
.optional()
|
||||
@@ -27,7 +29,7 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||
}),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -57,9 +59,9 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
||||
leaseId: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().min(1).trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -100,9 +102,9 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
||||
if (valMs > daysToMillisecond(1))
|
||||
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "TTL must be less than a day" });
|
||||
}),
|
||||
projectId: z.string(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().min(1).trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -125,34 +127,36 @@ export const registerDynamicSecretLeaseRouter = async (server: FastifyZodProvide
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:slug",
|
||||
url: "/:leaseId",
|
||||
method: "GET",
|
||||
schema: {
|
||||
params: z.object({
|
||||
slug: z.string()
|
||||
leaseId: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
leases: DynamicSecretLeasesSchema.array()
|
||||
lease: DynamicSecretLeasesSchema.extend({
|
||||
dynamicSecret: SanitizedDynamicSecretSchema
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const leases = await server.services.dynamicSecretLease.listLeases({
|
||||
const lease = await server.services.dynamicSecretLease.getLeaseDetails({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
slug: req.params.slug,
|
||||
leaseId: req.params.leaseId,
|
||||
...req.query
|
||||
});
|
||||
return { leases };
|
||||
return { lease };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ms from "ms";
|
||||
import { z } from "zod";
|
||||
|
||||
import { DynamicSecretLeasesSchema } from "@app/db/schemas";
|
||||
import { daysToMillisecond } from "@app/lib/dates";
|
||||
import { removeTrailingSlash } from "@app/lib/fn";
|
||||
import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
|
||||
@@ -15,7 +16,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
method: "POST",
|
||||
schema: {
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
provider: DynamicSecretProviderSchema,
|
||||
defaultTTL: z.string().superRefine((val, ctx) => {
|
||||
const valMs = ms(val);
|
||||
@@ -37,8 +38,8 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
})
|
||||
.nullable(),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string(),
|
||||
slug: z.string().toLowerCase()
|
||||
environment: z.string().min(1),
|
||||
slug: z.string().min(1).toLowerCase()
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -67,9 +68,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
slug: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string(),
|
||||
environment: z.string().min(1),
|
||||
data: z.object({
|
||||
inputs: z.any().optional(),
|
||||
defaultTTL: z
|
||||
@@ -113,7 +114,7 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
actorOrgId: req.permission.orgId,
|
||||
slug: req.params.slug,
|
||||
path: req.body.path,
|
||||
projectId: req.body.projectId,
|
||||
projectSlug: req.body.projectSlug,
|
||||
environment: req.body.environment,
|
||||
...req.body.data
|
||||
});
|
||||
@@ -129,9 +130,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
slug: z.string()
|
||||
}),
|
||||
body: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -161,9 +162,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
slug: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -192,9 +193,9 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
method: "GET",
|
||||
schema: {
|
||||
querystring: z.object({
|
||||
projectId: z.string(),
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string()
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
@@ -214,4 +215,36 @@ export const registerDynamicSecretRouter = async (server: FastifyZodProvider) =>
|
||||
return { dynamicSecrets: dynamicSecretCfgs };
|
||||
}
|
||||
});
|
||||
|
||||
server.route({
|
||||
url: "/:slug/leases",
|
||||
method: "GET",
|
||||
schema: {
|
||||
params: z.object({
|
||||
slug: z.string()
|
||||
}),
|
||||
querystring: z.object({
|
||||
projectSlug: z.string().min(1),
|
||||
path: z.string().trim().default("/").transform(removeTrailingSlash),
|
||||
environment: z.string().min(1)
|
||||
}),
|
||||
response: {
|
||||
200: z.object({
|
||||
leases: DynamicSecretLeasesSchema.array()
|
||||
})
|
||||
}
|
||||
},
|
||||
onRequest: verifyAuth([AuthMode.JWT, AuthMode.IDENTITY_ACCESS_TOKEN]),
|
||||
handler: async (req) => {
|
||||
const leases = await server.services.dynamicSecretLease.listLeases({
|
||||
actor: req.permission.type,
|
||||
actorId: req.permission.id,
|
||||
actorAuthMethod: req.permission.authMethod,
|
||||
actorOrgId: req.permission.orgId,
|
||||
slug: req.params.slug,
|
||||
...req.query
|
||||
});
|
||||
return { leases };
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,10 +1,71 @@
|
||||
import { Knex } from "knex";
|
||||
|
||||
import { TDbClient } from "@app/db";
|
||||
import { TableName } from "@app/db/schemas";
|
||||
import { ormify } from "@app/lib/knex";
|
||||
import { DynamicSecretLeasesSchema, TableName } from "@app/db/schemas";
|
||||
import { DatabaseError } from "@app/lib/errors";
|
||||
import { ormify, selectAllTableCols } from "@app/lib/knex";
|
||||
|
||||
export type TDynamicSecretLeaseDALFactory = ReturnType<typeof dynamicSecretLeaseDALFactory>;
|
||||
|
||||
export const dynamicSecretLeaseDALFactory = (db: TDbClient) => {
|
||||
const orm = ormify(db, TableName.DynamicSecretLease);
|
||||
return orm;
|
||||
|
||||
const findById = async (id: string, tx?: Knex) => {
|
||||
try {
|
||||
const doc = await (tx || db)(TableName.DynamicSecretLease)
|
||||
.where({ id })
|
||||
.first()
|
||||
.join(
|
||||
TableName.DynamicSecret,
|
||||
`${TableName.DynamicSecretLease}.dynamicSecretId`,
|
||||
`${TableName.DynamicSecret}.id`
|
||||
)
|
||||
.select(selectAllTableCols(TableName.DynamicSecretLease))
|
||||
.select(
|
||||
db.ref("id").withSchema(TableName.DynamicSecret).as("dynId"),
|
||||
db.ref("slug").withSchema(TableName.DynamicSecret).as("dynSlug"),
|
||||
db.ref("version").withSchema(TableName.DynamicSecret).as("dynVersion"),
|
||||
db.ref("type").withSchema(TableName.DynamicSecret).as("dynType"),
|
||||
db.ref("defaultTTL").withSchema(TableName.DynamicSecret).as("dynDefaultTTL"),
|
||||
db.ref("maxTTL").withSchema(TableName.DynamicSecret).as("dynMaxTTL"),
|
||||
db.ref("inputIV").withSchema(TableName.DynamicSecret).as("dynInputIV"),
|
||||
db.ref("inputTag").withSchema(TableName.DynamicSecret).as("dynInputTag"),
|
||||
db.ref("inputCiphertext").withSchema(TableName.DynamicSecret).as("dynInputCiphertext"),
|
||||
db.ref("algorithm").withSchema(TableName.DynamicSecret).as("dynAlgorithm"),
|
||||
db.ref("keyEncoding").withSchema(TableName.DynamicSecret).as("dynKeyEncoding"),
|
||||
db.ref("folderId").withSchema(TableName.DynamicSecret).as("dynFolderId"),
|
||||
db.ref("status").withSchema(TableName.DynamicSecret).as("dynStatus"),
|
||||
db.ref("statusDetails").withSchema(TableName.DynamicSecret).as("dynStatusDetails"),
|
||||
db.ref("createdAt").withSchema(TableName.DynamicSecret).as("dynCreatedAt"),
|
||||
db.ref("updatedAt").withSchema(TableName.DynamicSecret).as("dynUpdatedAt")
|
||||
);
|
||||
if (!doc) return;
|
||||
|
||||
return {
|
||||
...DynamicSecretLeasesSchema.parse(doc),
|
||||
dynamicSecret: {
|
||||
id: doc.dynId,
|
||||
slug: doc.dynSlug,
|
||||
version: doc.dynVersion,
|
||||
type: doc.dynType,
|
||||
defaultTTL: doc.dynDefaultTTL,
|
||||
maxTTL: doc.dynMaxTTL,
|
||||
inputIV: doc.dynInputIV,
|
||||
inputTag: doc.dynInputTag,
|
||||
inputCiphertext: doc.dynInputCiphertext,
|
||||
algorithm: doc.dynAlgorithm,
|
||||
keyEncoding: doc.dynKeyEncoding,
|
||||
folderId: doc.dynFolderId,
|
||||
status: doc.dynStatus,
|
||||
statusDetails: doc.dynStatusDetails,
|
||||
createdAt: doc.dynCreatedAt,
|
||||
updatedAt: doc.dynUpdatedAt
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
throw new DatabaseError({ error, name: "DynamicSecretLeaseFindById" });
|
||||
}
|
||||
};
|
||||
|
||||
return { ...orm, findById };
|
||||
};
|
||||
|
||||
@@ -9,12 +9,14 @@ import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TDynamicSecretDALFactory } from "../dynamic-secret/dynamic-secret-dal";
|
||||
import { DynamicSecretProviders, TDynamicProviderFns } from "../dynamic-secret/providers/models";
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TDynamicSecretLeaseDALFactory } from "./dynamic-secret-lease-dal";
|
||||
import { TDynamicSecretLeaseQueueServiceFactory } from "./dynamic-secret-lease-queue";
|
||||
import {
|
||||
TCreateDynamicSecretLeaseDTO,
|
||||
TDeleteDynamicSecretLeaseDTO,
|
||||
TDetailsDynamicSecretLeaseDTO,
|
||||
TListDynamicSecretLeasesDTO,
|
||||
TRenewDynamicSecretLeaseDTO
|
||||
} from "./dynamic-secret-lease-types";
|
||||
@@ -26,6 +28,7 @@ type TDynamicSecretLeaseServiceFactoryDep = {
|
||||
dynamicSecretQueueService: TDynamicSecretLeaseQueueServiceFactory;
|
||||
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
||||
};
|
||||
|
||||
export type TDynamicSecretLeaseServiceFactory = ReturnType<typeof dynamicSecretLeaseServiceFactory>;
|
||||
@@ -36,19 +39,24 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
dynamicSecretDAL,
|
||||
folderDAL,
|
||||
permissionService,
|
||||
dynamicSecretQueueService
|
||||
dynamicSecretQueueService,
|
||||
projectDAL
|
||||
}: TDynamicSecretLeaseServiceFactoryDep) => {
|
||||
const create = async ({
|
||||
environment,
|
||||
path,
|
||||
slug,
|
||||
projectId,
|
||||
projectSlug,
|
||||
actor,
|
||||
actorId,
|
||||
actorOrgId,
|
||||
actorAuthMethod,
|
||||
ttl
|
||||
}: TCreateDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -57,7 +65,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionActions.Create,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -102,11 +110,15 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path,
|
||||
environment,
|
||||
leaseId
|
||||
}: TRenewDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -125,12 +137,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({
|
||||
id: dynamicSecretLease.dynamicSecretId,
|
||||
folderId: folder.id
|
||||
});
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
|
||||
const dynamicSecretCfg = dynamicSecretLease.dynamicSecret;
|
||||
const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders];
|
||||
const decryptedStoredInput = JSON.parse(
|
||||
infisicalSymmetricDecrypt({
|
||||
@@ -168,12 +175,16 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
leaseId,
|
||||
environment,
|
||||
path,
|
||||
projectId,
|
||||
projectSlug,
|
||||
actor,
|
||||
actorId,
|
||||
actorOrgId,
|
||||
actorAuthMethod
|
||||
}: TDeleteDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -182,7 +193,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionActions.Delete,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -192,12 +203,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
const dynamicSecretCfg = await dynamicSecretDAL.findOne({
|
||||
id: dynamicSecretLease.dynamicSecretId,
|
||||
folderId: folder.id
|
||||
});
|
||||
if (!dynamicSecretCfg) throw new BadRequestError({ message: "Dynamic secret not found" });
|
||||
|
||||
const dynamicSecretCfg = dynamicSecretLease.dynamicSecret;
|
||||
const selectedProvider = dynamicSecretProviders[dynamicSecretCfg.type as DynamicSecretProviders];
|
||||
const decryptedStoredInput = JSON.parse(
|
||||
infisicalSymmetricDecrypt({
|
||||
@@ -220,11 +226,15 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
slug,
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
projectSlug,
|
||||
actorOrgId,
|
||||
environment,
|
||||
actorAuthMethod
|
||||
}: TListDynamicSecretLeasesDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -233,7 +243,7 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Edit,
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||
);
|
||||
|
||||
@@ -247,10 +257,46 @@ export const dynamicSecretLeaseServiceFactory = ({
|
||||
return dynamicSecretLeases;
|
||||
};
|
||||
|
||||
const getLeaseDetails = async ({
|
||||
projectSlug,
|
||||
actorOrgId,
|
||||
path,
|
||||
environment,
|
||||
actor,
|
||||
actorId,
|
||||
leaseId,
|
||||
actorAuthMethod
|
||||
}: TDetailsDynamicSecretLeaseDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
projectId,
|
||||
actorAuthMethod,
|
||||
actorOrgId
|
||||
);
|
||||
ForbiddenError.from(permission).throwUnlessCan(
|
||||
ProjectPermissionActions.Read,
|
||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||
);
|
||||
|
||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||
|
||||
const dynamicSecretLease = await dynamicSecretLeaseDAL.findById(leaseId);
|
||||
if (!dynamicSecretLease) throw new BadRequestError({ message: "Dynamic secret lease not found" });
|
||||
|
||||
return dynamicSecretLease;
|
||||
};
|
||||
|
||||
return {
|
||||
create,
|
||||
listLeases,
|
||||
revokeLease,
|
||||
renewLease
|
||||
renewLease,
|
||||
getLeaseDetails
|
||||
};
|
||||
};
|
||||
|
||||
@@ -9,23 +9,34 @@ export type TCreateDynamicSecretLeaseDTO = {
|
||||
path: string;
|
||||
environment: string;
|
||||
ttl?: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDetailsDynamicSecretLeaseDTO = {
|
||||
leaseId: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TListDynamicSecretLeasesDTO = {
|
||||
slug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDeleteDynamicSecretLeaseDTO = {
|
||||
leaseId: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TRenewDynamicSecretLeaseDTO = {
|
||||
leaseId: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
ttl?: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { BadRequestError } from "@app/lib/errors";
|
||||
|
||||
import { TDynamicSecretLeaseDALFactory } from "../dynamic-secret-lease/dynamic-secret-lease-dal";
|
||||
import { TDynamicSecretLeaseQueueServiceFactory } from "../dynamic-secret-lease/dynamic-secret-lease-queue";
|
||||
import { TProjectDALFactory } from "../project/project-dal";
|
||||
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
|
||||
import { TDynamicSecretDALFactory } from "./dynamic-secret-dal";
|
||||
import {
|
||||
@@ -26,6 +27,7 @@ type TDynamicSecretServiceFactoryDep = {
|
||||
dynamicSecretProviders: Record<DynamicSecretProviders, TDynamicProviderFns>;
|
||||
dynamicSecretQueueService: Pick<TDynamicSecretLeaseQueueServiceFactory, "pruneDynamicSecret">;
|
||||
folderDAL: Pick<TSecretFolderDALFactory, "findBySecretPath">;
|
||||
projectDAL: Pick<TProjectDALFactory, "findProjectBySlug">;
|
||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||
};
|
||||
|
||||
@@ -37,7 +39,8 @@ export const dynamicSecretServiceFactory = ({
|
||||
folderDAL,
|
||||
dynamicSecretProviders,
|
||||
permissionService,
|
||||
dynamicSecretQueueService
|
||||
dynamicSecretQueueService,
|
||||
projectDAL
|
||||
}: TDynamicSecretServiceFactoryDep) => {
|
||||
const create = async ({
|
||||
path,
|
||||
@@ -47,11 +50,15 @@ export const dynamicSecretServiceFactory = ({
|
||||
maxTTL,
|
||||
provider,
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
actorOrgId,
|
||||
defaultTTL,
|
||||
actorAuthMethod
|
||||
}: TCreateDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -96,7 +103,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
defaultTTL,
|
||||
inputs,
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path,
|
||||
actor,
|
||||
actorId,
|
||||
@@ -104,6 +111,11 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorAuthMethod
|
||||
}: TUpdateDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -161,11 +173,16 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
projectSlug,
|
||||
slug,
|
||||
path,
|
||||
environment
|
||||
}: TDeleteDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -201,7 +218,7 @@ export const dynamicSecretServiceFactory = ({
|
||||
|
||||
const getDetails = async ({
|
||||
slug,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path,
|
||||
environment,
|
||||
actorAuthMethod,
|
||||
@@ -209,6 +226,10 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorId,
|
||||
actor
|
||||
}: TDetailsDynamicSecretDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
@@ -244,10 +265,14 @@ export const dynamicSecretServiceFactory = ({
|
||||
actorOrgId,
|
||||
actorId,
|
||||
actor,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path,
|
||||
environment
|
||||
}: TListDynamicSecretsDTO) => {
|
||||
const project = await projectDAL.findProjectBySlug(projectSlug, actorOrgId);
|
||||
if (!project) throw new BadRequestError({ message: "Project not found" });
|
||||
|
||||
const projectId = project.id;
|
||||
const { permission } = await permissionService.getProjectPermission(
|
||||
actor,
|
||||
actorId,
|
||||
|
||||
@@ -18,7 +18,8 @@ export type TCreateDynamicSecretDTO = {
|
||||
path: string;
|
||||
environment: string;
|
||||
slug: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TUpdateDynamicSecretDTO = {
|
||||
slug: string;
|
||||
@@ -28,21 +29,25 @@ export type TUpdateDynamicSecretDTO = {
|
||||
path: string;
|
||||
environment: string;
|
||||
inputs?: TProvider["inputs"];
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDeleteDynamicSecretDTO = {
|
||||
slug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TDetailsDynamicSecretDTO = {
|
||||
slug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
export type TListDynamicSecretsDTO = {
|
||||
path: string;
|
||||
environment: string;
|
||||
} & TProjectPermission;
|
||||
projectSlug: string;
|
||||
} & Omit<TProjectPermission, "projectId">;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { DynamicSecretSqlDBSchema, TDynamicProviderFns } from "./models";
|
||||
const EXTERNAL_REQUEST_TIMEOUT = 10 * 1000;
|
||||
|
||||
const generatePassword = (size?: number) => {
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$%^&*()_+-=[]{}|;,./<>";
|
||||
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~!*'$#";
|
||||
return customAlphabet(charset, 20)(size);
|
||||
};
|
||||
|
||||
@@ -62,7 +62,7 @@ export const SqlDatabaseProvider = (): TDynamicProviderFns => {
|
||||
|
||||
await db.raw(creationStatement.toString());
|
||||
await db.destroy();
|
||||
return { entityId: username, data: { username, password } };
|
||||
return { entityId: username, data: { DB_USERNAME: username, DB_PASSWORD: password } };
|
||||
};
|
||||
|
||||
const revoke = async (inputs: unknown, entityId: string) => {
|
||||
|
||||
@@ -21,8 +21,8 @@ export const useCreateDynamicSecret = () => {
|
||||
);
|
||||
return data.dynamicSecret;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectId, environment }));
|
||||
onSuccess: (_, { path, environment, projectSlug }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -38,8 +38,8 @@ export const useUpdateDynamicSecret = () => {
|
||||
);
|
||||
return data.dynamicSecret;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectId, environment }));
|
||||
onSuccess: (_, { path, environment, projectSlug }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -55,8 +55,8 @@ export const useDeleteDynamicSecret = () => {
|
||||
);
|
||||
return data.dynamicSecret;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectId, environment }));
|
||||
onSuccess: (_, { path, environment, projectSlug }) => {
|
||||
queryClient.invalidateQueries(dynamicSecretKeys.list({ path, projectSlug, environment }));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -6,25 +6,25 @@ import { TDetailsDynamicSecretDTO, TDynamicSecret, TListDynamicSecretDTO } from
|
||||
|
||||
export const dynamicSecretKeys = {
|
||||
list: ({
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path
|
||||
}: Pick<TListDynamicSecretDTO, "path" | "environment" | "projectId">) =>
|
||||
[{ projectId, environment, path }, "dynamic-secrets"] as const,
|
||||
details: ({ path, environment, projectId, slug }: TDetailsDynamicSecretDTO) =>
|
||||
[{ projectId, path, environment, slug }, "dynamic-secret-details"] as const
|
||||
}: 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
|
||||
};
|
||||
|
||||
export const useGetDynamicSecrets = ({ projectId, environment, path }: TListDynamicSecretDTO) => {
|
||||
export const useGetDynamicSecrets = ({ projectSlug, environment, path }: TListDynamicSecretDTO) => {
|
||||
return useQuery({
|
||||
queryKey: dynamicSecretKeys.list({ path, environment, projectId }),
|
||||
enabled: Boolean(projectId && environment && path),
|
||||
queryKey: dynamicSecretKeys.list({ path, environment, projectSlug }),
|
||||
enabled: Boolean(projectSlug && environment && path),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ dynamicSecrets: TDynamicSecret[] }>(
|
||||
"/api/v1/dynamic-secrets",
|
||||
{
|
||||
params: {
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path
|
||||
}
|
||||
@@ -37,20 +37,20 @@ export const useGetDynamicSecrets = ({ projectId, environment, path }: TListDyna
|
||||
};
|
||||
|
||||
export const useGetDynamicSecretDetails = ({
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path,
|
||||
slug
|
||||
}: TDetailsDynamicSecretDTO) => {
|
||||
return useQuery({
|
||||
queryKey: dynamicSecretKeys.details({ path, environment, projectId, slug }),
|
||||
enabled: Boolean(projectId && environment && path && slug),
|
||||
queryKey: dynamicSecretKeys.details({ path, environment, projectSlug, slug }),
|
||||
enabled: Boolean(projectSlug && environment && path && slug),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{
|
||||
dynamicSecret: TDynamicSecret & { inputs: unknown };
|
||||
}>(`/api/v1/dynamic-secrets/${slug}`, {
|
||||
params: {
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ export type TDynamicSecretProvider = {
|
||||
};
|
||||
|
||||
export type TCreateDynamicSecretDTO = {
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
provider: TDynamicSecretProvider;
|
||||
defaultTTL: string;
|
||||
maxTTL?: string;
|
||||
@@ -51,7 +51,7 @@ export type TCreateDynamicSecretDTO = {
|
||||
|
||||
export type TUpdateDynamicSecretDTO = {
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
data: {
|
||||
@@ -63,20 +63,20 @@ export type TUpdateDynamicSecretDTO = {
|
||||
};
|
||||
|
||||
export type TListDynamicSecretDTO = {
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
};
|
||||
|
||||
export type TDeleteDynamicSecretDTO = {
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
slug: string;
|
||||
};
|
||||
|
||||
export type TDetailsDynamicSecretDTO = {
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
slug: string;
|
||||
|
||||
@@ -25,9 +25,9 @@ export const useCreateDynamicSecretLease = () => {
|
||||
);
|
||||
return data;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId, slug }) => {
|
||||
onSuccess: (_, { path, environment, projectSlug, slug }) => {
|
||||
queryClient.invalidateQueries(
|
||||
dynamicSecretLeaseKeys.list({ path, projectId, environment, slug })
|
||||
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -44,9 +44,9 @@ export const useRenewDynamicSecretLease = () => {
|
||||
);
|
||||
return data.lease;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId, slug }) => {
|
||||
onSuccess: (_, { path, environment, projectSlug, slug }) => {
|
||||
queryClient.invalidateQueries(
|
||||
dynamicSecretLeaseKeys.list({ path, projectId, environment, slug })
|
||||
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -63,9 +63,9 @@ export const useRevokeDynamicSecretLease = () => {
|
||||
);
|
||||
return data.lease;
|
||||
},
|
||||
onSuccess: (_, { path, environment, projectId, slug }) => {
|
||||
onSuccess: (_, { path, environment, projectSlug, slug }) => {
|
||||
queryClient.invalidateQueries(
|
||||
dynamicSecretLeaseKeys.list({ path, projectId, environment, slug })
|
||||
dynamicSecretLeaseKeys.list({ path, projectSlug, environment, slug })
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -5,26 +5,26 @@ import { apiRequest } from "@app/config/request";
|
||||
import { TDynamicSecretLease, TListDynamicSecretLeaseDTO } from "./types";
|
||||
|
||||
export const dynamicSecretLeaseKeys = {
|
||||
list: ({ projectId, environment, path, slug }: TListDynamicSecretLeaseDTO) =>
|
||||
[{ projectId, environment, path, slug }, "dynamic-secret-leases"] as const
|
||||
list: ({ projectSlug, environment, path, slug }: TListDynamicSecretLeaseDTO) =>
|
||||
[{ projectSlug, environment, path, slug }, "dynamic-secret-leases"] as const
|
||||
};
|
||||
|
||||
export const useGetDynamicSecretLeases = ({
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path,
|
||||
slug,
|
||||
enabled = true
|
||||
}: TListDynamicSecretLeaseDTO) => {
|
||||
return useQuery({
|
||||
queryKey: dynamicSecretLeaseKeys.list({ path, environment, projectId, slug }),
|
||||
enabled: Boolean(projectId && environment && path && slug && enabled),
|
||||
queryKey: dynamicSecretLeaseKeys.list({ path, environment, projectSlug, slug }),
|
||||
enabled: Boolean(projectSlug && environment && path && slug && enabled),
|
||||
queryFn: async () => {
|
||||
const { data } = await apiRequest.get<{ leases: TDynamicSecretLease[] }>(
|
||||
`/api/v1/dynamic-secrets/leases/${slug}`,
|
||||
`/api/v1/dynamic-secrets/${slug}/leases`,
|
||||
{
|
||||
params: {
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export type TDynamicSecretLease = {
|
||||
|
||||
export type TCreateDynamicSecretLeaseDTO = {
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
ttl?: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
@@ -25,14 +25,14 @@ export type TRenewDynamicSecretLeaseDTO = {
|
||||
leaseId: string;
|
||||
slug: string;
|
||||
ttl?: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
};
|
||||
|
||||
export type TListDynamicSecretLeaseDTO = {
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
enabled?: boolean;
|
||||
@@ -41,7 +41,7 @@ export type TListDynamicSecretLeaseDTO = {
|
||||
export type TRevokeDynamicSecretLeaseDTO = {
|
||||
leaseId: string;
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
path: string;
|
||||
environment: string;
|
||||
};
|
||||
|
||||
@@ -69,6 +69,7 @@ export const SecretMainPage = () => {
|
||||
// env slug
|
||||
const environment = router.query.env as string;
|
||||
const workspaceId = currentWorkspace?.id || "";
|
||||
const projectSlug = currentWorkspace?.slug || "";
|
||||
const secretPath = (router.query.secretPath as string) || "/";
|
||||
const canReadSecret = permission.can(
|
||||
ProjectPermissionActions.Read,
|
||||
@@ -139,7 +140,7 @@ export const SecretMainPage = () => {
|
||||
});
|
||||
|
||||
const { data: dynamicSecrets, isLoading: isDynamicSecretLoading } = useGetDynamicSecrets({
|
||||
projectId: workspaceId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path: secretPath
|
||||
});
|
||||
@@ -258,6 +259,7 @@ export const SecretMainPage = () => {
|
||||
importedSecrets={importedSecrets}
|
||||
environment={environment}
|
||||
workspaceId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
secretPath={secretPath}
|
||||
isVisible={isVisible}
|
||||
filter={filter}
|
||||
@@ -316,7 +318,7 @@ export const SecretMainPage = () => {
|
||||
<DynamicSecretListView
|
||||
sortDir={sortDir}
|
||||
environment={environment}
|
||||
workspaceId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
secretPath={secretPath}
|
||||
dynamicSecrets={dynamicSecrets || []}
|
||||
/>
|
||||
|
||||
@@ -62,7 +62,9 @@ type Props = {
|
||||
// swtich the secrets type as it gets decrypted after api call
|
||||
importedSecrets?: Array<Omit<TImportedSecrets, "secrets"> & { secrets: DecryptedSecret[] }>;
|
||||
environment: string;
|
||||
// @depreciated will be moving all these details to zustand
|
||||
workspaceId: string;
|
||||
projectSlug: string;
|
||||
secretPath?: string;
|
||||
filter: Filter;
|
||||
tags?: WsTag[];
|
||||
@@ -81,6 +83,7 @@ export const ActionBar = ({
|
||||
importedSecrets = [],
|
||||
environment,
|
||||
workspaceId,
|
||||
projectSlug,
|
||||
secretPath = "/",
|
||||
filter,
|
||||
tags = [],
|
||||
@@ -443,7 +446,7 @@ export const ActionBar = ({
|
||||
<CreateDynamicSecretForm
|
||||
isOpen={popUp.addDynamicSecret.isOpen}
|
||||
onToggle={(isOpen) => handlePopUpToggle("addDynamicSecret", isOpen)}
|
||||
workspaceId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
environment={environment}
|
||||
secretPath={secretPath}
|
||||
/>
|
||||
|
||||
@@ -11,7 +11,7 @@ import { SqlDatabaseInputForm } from "./SqlDatabaseInputForm";
|
||||
type Props = {
|
||||
isOpen?: boolean;
|
||||
onToggle: (isOpen: boolean) => void;
|
||||
workspaceId: string;
|
||||
projectSlug:string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
};
|
||||
@@ -24,7 +24,7 @@ enum WizardSteps {
|
||||
export const CreateDynamicSecretForm = ({
|
||||
isOpen,
|
||||
onToggle,
|
||||
workspaceId,
|
||||
projectSlug,
|
||||
environment,
|
||||
secretPath
|
||||
}: Props) => {
|
||||
@@ -92,7 +92,7 @@ export const CreateDynamicSecretForm = ({
|
||||
<SqlDatabaseInputForm
|
||||
onCompleted={handleFormReset}
|
||||
onCancel={handleFormReset}
|
||||
projectId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
secretPath={secretPath}
|
||||
environment={environment}
|
||||
/>
|
||||
|
||||
@@ -58,7 +58,7 @@ type Props = {
|
||||
onCompleted: () => void;
|
||||
onCancel: () => void;
|
||||
secretPath: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
environment: string;
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ export const SqlDatabaseInputForm = ({
|
||||
onCancel,
|
||||
environment,
|
||||
secretPath,
|
||||
projectId
|
||||
projectSlug
|
||||
}: Props) => {
|
||||
const {
|
||||
control,
|
||||
@@ -89,7 +89,7 @@ export const SqlDatabaseInputForm = ({
|
||||
slug,
|
||||
path: secretPath,
|
||||
defaultTTL,
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment
|
||||
});
|
||||
onCompleted();
|
||||
|
||||
@@ -13,20 +13,6 @@ import { useTimedReset } from "@app/hooks";
|
||||
import { useCreateDynamicSecretLease } from "@app/hooks/api";
|
||||
import { DynamicSecretProviders } from "@app/hooks/api/dynamicSecret/types";
|
||||
|
||||
const formSchema = z.object({
|
||||
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||
});
|
||||
type TForm = z.infer<typeof formSchema>;
|
||||
|
||||
type Props = {
|
||||
onClose: () => void;
|
||||
slug: string;
|
||||
provider: DynamicSecretProviders;
|
||||
projectId: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
};
|
||||
|
||||
const OutputDisplay = ({
|
||||
value,
|
||||
label,
|
||||
@@ -68,14 +54,14 @@ const OutputDisplay = ({
|
||||
};
|
||||
|
||||
const renderOutputForm = (provider: DynamicSecretProviders, data: unknown) => {
|
||||
const { username, password } = data as { username: string; password: string };
|
||||
const { DB_PASSWORD, DB_USERNAME } = data as { DB_USERNAME: string; DB_PASSWORD: string };
|
||||
if (provider === DynamicSecretProviders.SqlDatabase) {
|
||||
return (
|
||||
<div>
|
||||
<OutputDisplay label="Database User" value={username} />
|
||||
<OutputDisplay label="Database User" value={DB_USERNAME} />
|
||||
<OutputDisplay
|
||||
label="Database Password"
|
||||
value={password}
|
||||
value={DB_PASSWORD}
|
||||
helperText="Important: Copy this information now. It will disappear after this.opy this values as you won't be able to see it again."
|
||||
/>
|
||||
</div>
|
||||
@@ -84,9 +70,23 @@ const renderOutputForm = (provider: DynamicSecretProviders, data: unknown) => {
|
||||
return null;
|
||||
};
|
||||
|
||||
const formSchema = z.object({
|
||||
ttl: z.string().refine((val) => ms(val) > 0, "TTL must be a positive number")
|
||||
});
|
||||
type TForm = z.infer<typeof formSchema>;
|
||||
|
||||
type Props = {
|
||||
onClose: () => void;
|
||||
slug: string;
|
||||
provider: DynamicSecretProviders;
|
||||
projectSlug: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
};
|
||||
|
||||
export const CreateDynamicSecretLease = ({
|
||||
onClose,
|
||||
projectId,
|
||||
projectSlug,
|
||||
slug,
|
||||
provider,
|
||||
secretPath,
|
||||
@@ -107,11 +107,11 @@ export const CreateDynamicSecretLease = ({
|
||||
const createDynamicSecretLease = useCreateDynamicSecretLease();
|
||||
|
||||
const handleDynamicSecretLeaseCreate = async ({ ttl }: TForm) => {
|
||||
if(createDynamicSecretLease.isLoading) return;
|
||||
if (createDynamicSecretLease.isLoading) return;
|
||||
try {
|
||||
await createDynamicSecretLease.mutateAsync({
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path: secretPath,
|
||||
ttl,
|
||||
slug
|
||||
|
||||
@@ -28,7 +28,7 @@ import { RenewDynamicSecretLease } from "./RenewDynamicSecretLease";
|
||||
|
||||
type Props = {
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
onClickNewLease: () => void;
|
||||
@@ -36,7 +36,7 @@ type Props = {
|
||||
};
|
||||
|
||||
export const DynamicSecretLease = ({
|
||||
projectId,
|
||||
projectSlug,
|
||||
slug,
|
||||
environment,
|
||||
secretPath,
|
||||
@@ -48,7 +48,7 @@ export const DynamicSecretLease = ({
|
||||
"renewSecret"
|
||||
] as const);
|
||||
const { data: leases, isLoading: isLeaseLoading } = useGetDynamicSecretLeases({
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
path: secretPath,
|
||||
slug
|
||||
@@ -62,7 +62,7 @@ export const DynamicSecretLease = ({
|
||||
const { leaseId } = popUp.deleteSecret.data as { leaseId: string };
|
||||
await deleteDynamicSecretLease.mutateAsync({
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path: secretPath,
|
||||
slug,
|
||||
leaseId
|
||||
@@ -193,7 +193,7 @@ export const DynamicSecretLease = ({
|
||||
<ModalContent title="Renew Lease">
|
||||
<RenewDynamicSecretLease
|
||||
onClose={() => handlePopUpClose("renewSecret")}
|
||||
projectId={projectId}
|
||||
projectSlug={projectSlug}
|
||||
leaseId={(popUp.renewSecret?.data as { leaseId: string })?.leaseId}
|
||||
slug={slug}
|
||||
secretPath={secretPath}
|
||||
|
||||
@@ -40,7 +40,7 @@ const formatProviderName = (type: DynamicSecretProviders) => {
|
||||
type Props = {
|
||||
dynamicSecrets: TDynamicSecret[];
|
||||
environment: string;
|
||||
workspaceId: string;
|
||||
projectSlug: string;
|
||||
secretPath?: string;
|
||||
sortDir: SortDir;
|
||||
};
|
||||
@@ -48,7 +48,7 @@ type Props = {
|
||||
export const DynamicSecretListView = ({
|
||||
dynamicSecrets = [],
|
||||
environment,
|
||||
workspaceId,
|
||||
projectSlug,
|
||||
secretPath = "/",
|
||||
sortDir = SortDir.ASC
|
||||
}: Props) => {
|
||||
@@ -67,7 +67,7 @@ export const DynamicSecretListView = ({
|
||||
const { slug } = popUp.deleteDynamicSecret.data as TDynamicSecret;
|
||||
await deleteDynamicSecret.mutateAsync({
|
||||
environment,
|
||||
projectId: workspaceId,
|
||||
projectSlug,
|
||||
path: secretPath,
|
||||
slug
|
||||
});
|
||||
@@ -206,7 +206,7 @@ export const DynamicSecretListView = ({
|
||||
<DynamicSecretLease
|
||||
onClickNewLease={() => handlePopUpOpen("createDynamicSecretLease", secret)}
|
||||
onClose={() => handlePopUpClose("dynamicSecretLeases")}
|
||||
projectId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
key={secret.id}
|
||||
slug={secret.slug}
|
||||
secretPath={secretPath}
|
||||
@@ -226,7 +226,7 @@ export const DynamicSecretListView = ({
|
||||
(popUp.createDynamicSecretLease?.data as { type: DynamicSecretProviders })?.type
|
||||
}
|
||||
onClose={() => handlePopUpClose("createDynamicSecretLease")}
|
||||
projectId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
slug={(popUp.createDynamicSecretLease?.data as { slug: string })?.slug}
|
||||
secretPath={secretPath}
|
||||
environment={environment}
|
||||
@@ -240,7 +240,7 @@ export const DynamicSecretListView = ({
|
||||
<ModalContent title="Edit dynamic secret" className="max-w-3xl">
|
||||
<EditDynamicSecretForm
|
||||
onClose={() => handlePopUpClose("updateDynamicSecret")}
|
||||
projectId={workspaceId}
|
||||
projectSlug={projectSlug}
|
||||
slug={(popUp.updateDynamicSecret?.data as TDynamicSecret)?.slug}
|
||||
secretPath={secretPath}
|
||||
environment={environment}
|
||||
|
||||
@@ -9,7 +9,7 @@ import { EditDynamicSecretSqlProviderForm } from "./EditDynamicSecretSqlProvider
|
||||
type Props = {
|
||||
onClose: () => void;
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
};
|
||||
@@ -17,13 +17,13 @@ type Props = {
|
||||
export const EditDynamicSecretForm = ({
|
||||
slug,
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
onClose,
|
||||
secretPath
|
||||
}: Props) => {
|
||||
const { data: dynamicSecretDetails, isLoading: isDynamicSecretLoading } =
|
||||
useGetDynamicSecretDetails({
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
slug,
|
||||
path: secretPath
|
||||
@@ -49,7 +49,7 @@ export const EditDynamicSecretForm = ({
|
||||
>
|
||||
<EditDynamicSecretSqlProviderForm
|
||||
onClose={onClose}
|
||||
projectId={projectId}
|
||||
projectSlug={projectSlug}
|
||||
secretPath={secretPath}
|
||||
dynamicSecret={dynamicSecretDetails}
|
||||
environment={environment}
|
||||
|
||||
@@ -61,8 +61,8 @@ type Props = {
|
||||
onClose: () => void;
|
||||
dynamicSecret: TDynamicSecret & { inputs: unknown };
|
||||
secretPath: string;
|
||||
projectId: string;
|
||||
environment: string;
|
||||
projectSlug: string;
|
||||
};
|
||||
|
||||
export const EditDynamicSecretSqlProviderForm = ({
|
||||
@@ -70,7 +70,7 @@ export const EditDynamicSecretSqlProviderForm = ({
|
||||
dynamicSecret,
|
||||
environment,
|
||||
secretPath,
|
||||
projectId
|
||||
projectSlug
|
||||
}: Props) => {
|
||||
const {
|
||||
control,
|
||||
@@ -97,7 +97,7 @@ export const EditDynamicSecretSqlProviderForm = ({
|
||||
await updateDynamicSecret.mutateAsync({
|
||||
slug: dynamicSecret.slug,
|
||||
path: secretPath,
|
||||
projectId,
|
||||
projectSlug,
|
||||
environment,
|
||||
data: {
|
||||
maxTTL: maxTTL || undefined,
|
||||
|
||||
@@ -25,14 +25,14 @@ type Props = {
|
||||
onClose: () => void;
|
||||
leaseId: string;
|
||||
slug: string;
|
||||
projectId: string;
|
||||
projectSlug: string;
|
||||
environment: string;
|
||||
secretPath: string;
|
||||
};
|
||||
|
||||
export const RenewDynamicSecretLease = ({
|
||||
onClose,
|
||||
projectId,
|
||||
projectSlug,
|
||||
slug,
|
||||
leaseId,
|
||||
secretPath,
|
||||
@@ -57,7 +57,7 @@ export const RenewDynamicSecretLease = ({
|
||||
try {
|
||||
await renewDynamicSecretLease.mutateAsync({
|
||||
environment,
|
||||
projectId,
|
||||
projectSlug,
|
||||
path: secretPath,
|
||||
ttl,
|
||||
slug,
|
||||
|
||||
Reference in New Issue
Block a user